Ember JS - 如何在渲染之前等待异步函数响应
Ember JS - how to wait for async function to respond before render
我目前正在从事一个通过外包媒介提供给公司的项目。我的问题是关于渲染图像 src。
以前他们提供来自文件系统的图像。我们不再希望使用该方法,因为我们现在合并了 AWS S3 存储桶服务。我们还使用云端缓存,因此我们希望能够将 URL 从后端发送到前端(我们这样做),然后渲染图像。
在模型中,我有一个从后端检索图像 URL 和 returns 的函数,但是在渲染过程中图像 src 被设置为 [object Object] 我认为这是将 src 设置为函数而不是响应。
这是我们渲染检索 url
的函数
baseUrl: Ember.computed(async function () {
let adapter = this.store.adapterFor('article-image');
let ajax = this.get('ajax');
let path = ''
let API_URL = `${adapter.buildURL('article-image', this.id)}/original/${this.get('fileName')}`;
let promise = new Promise((resolve, reject) => {
ajax.request(API_URL, {
method: 'GET'
})
.then(function (response) {
resolve(response.path);
})
.catch(function (err) {
console.log('error');
console.log(err);
});
})
path = await promise
return path;
}),
这里是我们调用image.baseUrl的地方,这里src被设置为[object Object]
{{lazy-image
url=(concat image.baseUrl)
alt=(if title title (if image.title image.title 'Image'))
class=(if class class 'img-responsive')}}
在这里,您 return 从您计算的 属性 中得到一个 promise,它是一个对象,而不是一个字符串。
通常,我们实际上并不会在渲染您的组件之前等待 promise 解析。相反,我们首先渲染一些东西(比如加载 gif),然后在解决承诺时重新渲染图像。
这个问题有两种传统的解决方案。一种是在计算 属性.
中使用 PromiseProxy
return Ember.ObjectProxy.extend(Ember.PromiseProxyMixin).create({ promise });
您可以在模板中使用这样的代码:
{{#if image.baseUrl.isPending}}
<img src="loading.gif">
{{else}}
{{lazy-image url=(concat image.baseUrl.content) ...}}
{{/if}}
见https://api.emberjs.com/ember/release/classes/PromiseProxyMixin
第二种传统解决方案是使用 ember-concurrency
并避免 return 承诺的计算属性。这涉及重写您的代码以使其更具命令性。
见http://ember-concurrency.com/docs/introduction/
我通常更喜欢这个解决方案,因为使用 promise 代理会变得复杂且更难理解。
此外,如果您使用的是 Ember 的更现代版本(2.10 或更高版本),您可以尝试 ember-lifeline
,与 [= 相比,添加到项目中的代码要少得多12=],以及更简单的 api 足以满足此需求。 (根据您的代码示例,我假设您使用的是 Ember 的旧版本,但使用的是现代浏览器。)请参阅 https://ember-lifeline.github.io/ember-lifeline/
我目前正在从事一个通过外包媒介提供给公司的项目。我的问题是关于渲染图像 src。
以前他们提供来自文件系统的图像。我们不再希望使用该方法,因为我们现在合并了 AWS S3 存储桶服务。我们还使用云端缓存,因此我们希望能够将 URL 从后端发送到前端(我们这样做),然后渲染图像。
在模型中,我有一个从后端检索图像 URL 和 returns 的函数,但是在渲染过程中图像 src 被设置为 [object Object] 我认为这是将 src 设置为函数而不是响应。
这是我们渲染检索 url
的函数baseUrl: Ember.computed(async function () {
let adapter = this.store.adapterFor('article-image');
let ajax = this.get('ajax');
let path = ''
let API_URL = `${adapter.buildURL('article-image', this.id)}/original/${this.get('fileName')}`;
let promise = new Promise((resolve, reject) => {
ajax.request(API_URL, {
method: 'GET'
})
.then(function (response) {
resolve(response.path);
})
.catch(function (err) {
console.log('error');
console.log(err);
});
})
path = await promise
return path;
}),
这里是我们调用image.baseUrl的地方,这里src被设置为[object Object]
{{lazy-image
url=(concat image.baseUrl)
alt=(if title title (if image.title image.title 'Image'))
class=(if class class 'img-responsive')}}
在这里,您 return 从您计算的 属性 中得到一个 promise,它是一个对象,而不是一个字符串。
通常,我们实际上并不会在渲染您的组件之前等待 promise 解析。相反,我们首先渲染一些东西(比如加载 gif),然后在解决承诺时重新渲染图像。
这个问题有两种传统的解决方案。一种是在计算 属性.
中使用 PromiseProxyreturn Ember.ObjectProxy.extend(Ember.PromiseProxyMixin).create({ promise });
您可以在模板中使用这样的代码:
{{#if image.baseUrl.isPending}}
<img src="loading.gif">
{{else}}
{{lazy-image url=(concat image.baseUrl.content) ...}}
{{/if}}
见https://api.emberjs.com/ember/release/classes/PromiseProxyMixin
第二种传统解决方案是使用 ember-concurrency
并避免 return 承诺的计算属性。这涉及重写您的代码以使其更具命令性。
见http://ember-concurrency.com/docs/introduction/
我通常更喜欢这个解决方案,因为使用 promise 代理会变得复杂且更难理解。
此外,如果您使用的是 Ember 的更现代版本(2.10 或更高版本),您可以尝试 ember-lifeline
,与 [= 相比,添加到项目中的代码要少得多12=],以及更简单的 api 足以满足此需求。 (根据您的代码示例,我假设您使用的是 Ember 的旧版本,但使用的是现代浏览器。)请参阅 https://ember-lifeline.github.io/ember-lifeline/