1

我正在处理一堆记录并为第三方库生成一组哈希值。对于我的生活,我无法弄清楚为什么这不起作用。

export default Route.extend({
  model: function(params) {
   let qp = {viewName: 'byDay'};

  return this.store.query('job-receipt', qp).then(
   (receipts)=>
    all(
      receipts.map(
        (receipt)=>
          hash({
            stockCode: receipt.get('job')
                                   .then(job => job.get('stockCode'))
                                   .then(stockCode => stockCode.get('stockCode')),
            productClass: receipt.get('job')
                                  .then(job => job.get('stockCode'))
                                  .then(stockCode => stockCode.get('productClass'))
                                  .then(productClass => productClass.get('descr')),
            qtyRecvd: receipt.get('qtyRecvd')
          })
        )
      )
);

如果我继续重新进入路线,最终承诺会解决。如果我检查一下,productClass 承诺会直接被调用一个空值。为什么不等待 stockCode.get('productClass') 解决?我知道那里有真正的价值,因为它最终会解决。

我错过了一些超级基本的东西。我已经尝试过 Ember.get(thing, keypath) 等。这些不都返回承诺吗?RSVP.hash 不应该在继续之前等待所有承诺解决吗?就像我说的,我知道数据是好的,因为最终它会解决(而不是我只是不处理拒绝)。

编辑:

我将 productClass 承诺更改为:

productClass: receipt.get('job')
        .then(job => job.get('stockCode'))
        .then(stockCode => stockCode.get('productClass'))
        .then(productClass => {if (!productClass) {return 'foo';} return productClass.get('descr');})

现在报告每次都正确呈现,尽管是胡说八道。如果我导航到另一条路线,然后回到这条路线,它会完美呈现。所以,这让我很难相信我有某种数据错误。甚至一些股票代码在第一次运行时返回正确的产品类别 - 而不是“foo”。我什至不确定如何进一步调试。

编辑

刚看到这个。毕竟可能是一个错误。

[3.2.0+] Snapshot 相关数据为空 #5565

4

2 回答 2

2

事实证明这是一个错误。belongs-to.js 的错误导致模型在解决承诺之前不等待 internalModel 完成加载。下面链接的修复解决了这个问题

[BUGFIX] 如果已经加载,请使用 internalModel 承诺 #5562

于 2018-08-16T17:49:44.410 回答
1

我认为主要问题是“reciepts.job”很可能是 DS.belongsTo 关系,对吧?如果将其切换为 load job: DS.belongsTo('job', {async: false}),这将强制 ember-data 同步加载该属性(并且会省去很多麻烦)。但这需要数据在 json 响应中可用。

如果这不起作用,您应该调查ember concurrency。使用它来清理您的代码,使其看起来更简单。您必须填写一些空白或更改我误解您的用例的地方,但这可能是一个很好的起点。

这个想法是继续将所有异步调用分解为单独的任务。每个 ember-concurrencytask对象都会返回一个 Promise,因此您可以继续将它们捆绑在一起,直到您model可以像任何其他 Promise 一样返回它。

//model.js
import {task} from 'ember-concurrency';
.....

model() {
  return this.get('loadData').perform();
},
loadData: task(function*(){
  let reciepts = yield this.store.query('job-receipt', qp);
  let promises = reciepts.map(r => {
    return this.get('loadNestedData').perform(r);
  })
  return all(promises)
}),
loadNestedData: task(function*(reciept) {
  let job = yield receipt.get('job');
  return hash({
    stockCode: job.get('sockcode')
  });
})
于 2018-08-16T13:47:01.153 回答