我不是一个真正的承诺忍者,我知道我做错了什么。然而,我找不到一些特殊的/模拟的问题,我所拥有的。
问题是:我将Dexie.js包装器用于IndexedDB,这是异步的。我有一个全局数据库,它可以指向其他的dexie数据库。
function handleDatabases() {
var result = [];
db.jobs.orderBy('title').filter(function(job) {
return job.someBooleanCondition;
}).each(function(job, cursor) {
let jobDetails = new Dexie(job.correspondingDB);
jobDetails.version(1).stores({
details: 'key,value1,value2'
});
jobDetails.details.get(someKey).then(function(detail) {
result.push({job: job, detail: detail});
})
}).catch(function(error) {
console.log(error);
});
handleResult(result);
}因此,我用一个可能很奇怪的形式重写了它,但最终的目标是我可以使用数组result来处理一些更新。但是,由于它是异步的,所以它始终是空的,直到您在控制台中检查它,而在控制台中它从来不是空的。我如何将它重写为同步的呢?
发布于 2017-04-02 00:03:15
当结果只能异步可用时,不能期望返回该结果。
因此,您必须始终坚持承诺(每次都会返回),并且让您的函数也返回一个承诺。调用方必须使用then (或支持await )来允许(异步)访问结果。
而不是将{job: job, detail: detail}推到结果变量,而是返回它。它将成为jobDetails.details.get(..).then(..)的承诺价值。如果您也返回,您将有一系列的承诺,然后可以用Promise.all解决
避免创建新的承诺,因为这通常会导致promise constructor antipattern。
此外,避免使用在几个回调中使用的变量(如结果),而不将其作为参数传递。相反,尝试构建并返回该数组作为承诺的值,这样它就可以在下一个then回调中使用。
以下是建议的(未经测试的)代码:
function handleDatabases() {
db.jobs
.orderBy('title')
.filter(job => job.someBooleanCondition)
.toArray(jobs =>
jobs.map(job => {
let jobDetails = new Dexie(job.correspondingDB);
jobDetails.version(1).stores({
details: 'key,value1,value2'
});
return jobDetails.details.get(someKey)
.then(detail => ({job: job, detail: detail}))
}) // is returned
)
.then(result => Promise.all(result))
.then(handleResult)
.catch(error => console.log(error));
}https://stackoverflow.com/questions/43162677
复制相似问题