解决路线中的关键路径(或链接关系)

时间:2018-08-16 00:03:33

标签: ember.js ember-3

我正在处理一堆记录,并为第三方库生成一系列哈希。对于我的一生,我不知道为什么这行不通。

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承诺会直接使用null值调用。为什么不等待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’s related data has become null #5565

2 个答案:

答案 0 :(得分:2)

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

[BUGFIX] use internalModel promise if already loading #5562

答案 1 :(得分:1)

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

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

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

//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')
  });
})