for 循环中来自 LocalForage 的 JavaScript 链式 promise

标签 javascript for-loop promise chaining localforage

我正在尝试链接 LocalForage 库中的多个 getItem promise ,键是从数组中读取的。

问题: 我需要在所有 LocalForage promise 完成后触发 Resolve 或 Reject 回调。

这两种方法都没有正确的调用堆栈。有什么想法吗?

代码 1:

function load(keyHandlerPairs, correct, incorrect) {
    var result = {
                    resolved: 0,
                    rejects: 0,
                },
                p = new Promise(function (resolve, reject) {
                    //Retrieve objects from localstorage;
                    if ($.isArray(keyHandlerPairs)) {
                        for (var i = 0; i < keyHandlerPairs.length; i++) {
                            var kv = keyHandlerPairs[i];
                            lf.getItem(kv.key, kv.handler).then(
                                //Resolved
                                function () { console.log('resolved'); result.resolved++; }
                            );
                        }
                    } else {
                        var kv = keyHandlerPairs;
                        lf.getItem(kv.key, kv.handler);
                    }


                    if ((result.resolved + result.rejects) == keyHandlerPairs.length) {
                        console.log(result.resolved, result.rejects, keyHandlerPairs.length);
                        resolve(result);
                    } else {
                        console.log(result.resolved, result.rejects, keyHandlerPairs.length);
                        reject(result);
                    }
                }).then(correct, incorrect);
}

替代代码:

if ($.isArray(keyHandlerPairs)) {
                        var promises = [];
                        for (var i = 0; i < keyHandlerPairs.length; i++) {
                            var kv = keyHandlerPairs[i];
                            promises.push(lf.getItem(kv.key, kv.handler));
                        }

                        Promise
                            .all(promises)
                            .then(function (value) { console.log(value); result.resolved++; })
                            .catch(function (error) { console.log(error); result.rejects++; });

                    } else {
                        var kv = keyHandlerPairs;
                        lf.getItem(kv.key, kv.handler);
                    }

最佳答案

I need the Resolve or Reject callback to trigger AFTER all the LocalForage promises are finished.

是的。 lf.getItem 是异步的,但您在触发所有调用后立即测试 (result.resolved + result.rejects) == keyHandlerPairs.length.resolved.rejects 仍将为 0(请注意,无论如何您都不会增加拒绝数)。

首先,您不应使用 Promise 构造函数,除非为尚不支持 Promise 的单个异步 API 构造 Promise。不应该有任何逻辑,只是一个简单的调用。假设您想要使用 Promise.all 来等待所有并发运行的 Promise 并从中获取组合结果作为数组的 Promise。您的代码应如下所示:

if (!$.isArray(keyHandlerPairs))
    keyHandlerPairs = [keyHandlerPairs];
var promises = keyHandlerPairs.map(function(kv) {
    return lf.getItem(kv.key, kv.handler);
});
return Promise.all(promises);
<小时/>

好吧,现在假设您实际上并不关心结果以及所有 promise 是否成功,而只关心已履行的 promise 与拒绝的 promise 的数量。好的,没有用于此目的的 native 组合器函数,因此我们需要编写自己的组合器函数(并使用 Promise 构造函数)。但是,此功能应该是通用,并且与键值处理程序对无关。

Promise.countResolutions = function(promises) {
    var result = {fulfillments:0, rejections:0},
        len = 0;
    return new Promise(function(resolve, reject) {
        function addResult(type) {
            result[type]++;
            if (result.fulfillments+result.rejections == len)
                resolve(result);
            return true;
        }
        try {
            let i = 0;
            for (let promise of promises) {
                let called = false;
                i++;
                promise.then(function onfulfilled() {
                    if (!called) called = addResult("fulfillments");
                }, function onrejected() {
                    if (!called) called = addResult("rejections");
                });
            }
            len = i;
            if (result.fulfillments+result.rejections == len)
                resolve(result);
        } catch (e) {
            reject(e);
        }
    });
};

是的,它并不像乍一看那么简单(好吧,也许上面的版本有点太详细了)。但是一旦有了这个,您只需将第一个代码段中的 .all() 替换为 .countResolutions() 即可获得预期的结果。

关于for 循环中来自 LocalForage 的 JavaScript 链式 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26126796/

相关文章:

javascript - jQuery |如何从其他html中获取iframe的属性?

javascript - 使用自定义 css 和 javascript 使用 kentico 创建下拉列表

arrays - 即使在触发时,for 循环也不会将 JSON 元素添加到数组中

c++ - 在调用 future.get() 之前销毁 std::promise 是否可以?

javascript - 如何减少 phonegap 应用程序加载外部页面的响应时间?

java - 表达式的类型必须是数组类型但解析为 char

bash - 在 Bash 中使用 'For Loop' 中的输入变量

javascript - 异步函数没有按应有的顺序执行

javascript - async wait 嵌套时如何工作?

javascript - JS 和 Stripe 的限时访问