Разрешение ключевых путей (или цепочечных отношений) в маршруте
Я обрабатываю кучу записей и создаю массив хэшей для сторонней библиотеки. Что касается жизни, я не могу понять, почему это не работает.
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 (вещь, путь к ключу) и т. Д. Разве все это не возвращает обещания? Разве 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" - при первом запуске. Я даже не уверен, как отладить это дальше.
редактировать
Просто видел это. Может быть, ошибка в конце концов.
2 ответа
Оказывается, это ошибка. Из-за ошибки, связанной с assign-to.js, модель не дожидается завершения загрузки InternalModel, прежде чем разрешить обещание. Исправление, указанное ниже, решает проблему
[BUGFIX] использовать обещание internalModel, если уже загружается #5562
Я думаю, что главная проблема в том, что reciepts.job, скорее всего, относится к отношениям DS.belongsTo, верно? Если вы переключите его на загрузку job: DS.belongsTo('job', {async: false})
, это заставит ember-data загрузить это свойство синхронно (и сэкономит много головной боли). Но для этого необходимо, чтобы данные были доступны либо в ответе json.
Если это не сработает, вам следует исследовать параллелизм. Используйте это, чтобы очистить ваш код, чтобы выглядеть немного проще. Вы должны будете заполнить некоторые пробелы или изменить то, что я неправильно понял в вашем случае использования, но это, вероятно, хорошая отправная точка.
Идея состоит в том, чтобы продолжать разбивать все асинхронные вызовы на отдельные задачи. Каждый угольный параллелизм 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')
});
})