在 Dexie 迭代中使用 Promise

Emp*_*ess 2 javascript promise dexie

我并不是真正的承诺忍者,我知道我做错了。但是,我找不到与我遇到的问题相关的特定/类似问题。

问题:我对 IndexedDB 使用异步的 Dexie.js 包装器。我有一个全局数据库,它通向其他一些 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);
}
Run Code Online (Sandbox Code Playgroud)

我已经用一种可能奇怪的形式重写了它,但最终目标是我可以使用数组result来处理一些更新。但是,由于它是异步的,因此它始终为空,直到您在控制台中检查它,它永远不会为空。我怎样才能将其重写为同步?

tri*_*cot 5

当结果仅异步可用时,您不能期望返回该结果。

因此,您必须始终坚持承诺(每次都返回它们),并让您的函数也返回一个承诺。调用者必须使用then(或者await如果支持)来允许(异步)访问结果。

不要将 推{job: job, detail: detail}结果变量,而是返回它。它将成为 的承诺值jobDetails.details.get(..).then(..)。如果你也返回这个,你将有一系列的承诺,然后可以通过以下方式解决:Promise.all

避免创建新的 Promise,因为这通常会导致Promise 构造函数反模式

还要避免使用在多个回调中使用而不作为参数传递的变量(如results )。相反,尝试构造该数组并将其作为承诺值返回,以便可以在下一个回调中使用它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));
}
Run Code Online (Sandbox Code Playgroud)