Ember.js合并数据存储中两个对象为字符串的问题咨询
问题根源与解决方案
首先得给你点破核心问题:你现在的url和nickname变量其实不是字符串,而是Promise对象!Ember Data的store.find()方法是异步的,它返回的是一个Promise,只有当异步请求完成后,then回调里才能拿到真实的字符串值。
为什么会出现[Object object]和弹窗顺序混乱?
- 直接把两个Promise对象相加,JavaScript会把它们转换成
[object Promise]的字符串形式,所以你看到的是[Object object], [Object object]。 - Promise的回调是异步执行的,你后面的
alert(this.get('testFillSelect'))会在两个find的异步请求完成前就执行,所以先弹出了错误的合并结果,之后才会弹出then回调里的正确值。
解决方法:用RSVP.all等待所有异步请求完成
Ember内置了RSVP库来处理异步流程,我们可以用RSVP.all来等待两个Promise都成功resolve,再进行合并赋值:
preSelect: function (orgSiteId, orgId) { 'use strict'; // 把两个异步请求的Promise单独存起来 const urlPromise = this.get('store').find('orgSite', orgSiteId).then(orgSites => { return orgSites.get('url'); }); const nicknamePromise = this.get('store').find('org', orgId).then(orgs => { return orgs.get('nickname'); }); // 等待两个Promise都完成后再处理 Ember.RSVP.all([nicknamePromise, urlPromise]).then(results => { const [nickname, url] = results; this.set('testFillSelect', `${nickname}, ${url}`); alert(this.get('testFillSelect')); // 现在会弹出正确的合并值 }); }
关于计算属性/观察者的补充
如果你的testFillSelect需要随着orgSiteId或orgId的变化自动更新,那用计算属性会更符合Ember的设计思路。比如:
testFillSelect: Ember.computed('orgSiteId', 'orgId', function() { const orgSiteId = this.get('orgSiteId'); const orgId = this.get('orgId'); if (!orgSiteId || !orgId) return ''; return Ember.RSVP.all([ this.get('store').find('org', orgId).then(o => o.get('nickname')), this.get('store').find('orgSite', orgSiteId).then(os => os.get('url')) ]).then(([nickname, url]) => `${nickname}, ${url}`); })
这种情况下,计算属性会在orgSiteId或orgId变化时自动重新计算,返回一个Promise,你可以在模板里用{{await testFillSelect}}(Ember 3.16+支持)来渲染结果,或者在代码里用then处理。
至于观察者,Ember官方现在更推荐用计算属性或追踪属性(@tracked,Ember Octane+)来替代观察者,因为观察者容易引发不必要的重计算和时序问题,所以优先考虑上面的方案就好。
内容的提问来源于stack exchange,提问作者Dr Cox
相关产品推荐
相关产品推荐

