0

getItemLocalForage ライブラリから複数のプロミスをチェーンしようとしています。キーは配列から読み取られます。

問題: すべての 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);
                    }
4

1 に答える 1

1

すべての LocalForage 約束が終了した後にトリガーするには、Resolve または Reject コールバックが必要です。

はい。lf.getItem非同期ですが、(result.resolved + result.rejects) == keyHandlerPairs.lengthすべての呼び出しを開始した直後にテストしています。.resolvedとの両方.rejectsが引き続き使用されます0(とにかく拒否の数を増やすことはないことに注意してください)。

まず、Promisepromise をまだサポートしていない単一の非同期 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);

OK、ここで、実際には結果とすべての約束が成功したかどうかは気にせず、満たされた約束と拒否された約束の数だけを気にしていると仮定します。OK、これにはネイティブのコンビネーター関数がないので、独自に作成する必要があります (そして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);
        }
    });
};

はい、最初に見えるほど簡単ではありません (OK、上記のバージョンは少し詳細すぎるかもしれません)。しかし、これを取得したら.all()、最初のスニペットを に置き換えるだけで、期待どおりの結果が得られます。.countResolutions()

于 2014-09-30T19:06:18.343 に答える