web-dev-qa-db-ja.com

jQuery Deferredの配列をどのように使用しますか?

データを特定の順序でロードする必要があるアプリケーションがあります。ルートURL、次にスキーマ、最後にさまざまなデータオブジェクトのスキーマとURLでアプリケーションを初期化します。ユーザーがアプリケーションをナビゲートすると、データオブジェクトがロードされ、スキーマに対して検証され、表示されます。ユーザーがデータをCRUDすると、スキーマは初回の検証を提供します。

初期化に問題があります。 Ajax呼び出しを使用してルートオブジェクト$ .when()を取得し、各スキーマオブジェクトに1つずつ、promiseの配列を作成します。動作します。コンソールにフェッチが表示されます。

その後、すべてのスキーマのフェッチが表示されるため、各$ .ajax()呼び出しが機能します。 fetchschemas()は実際にpromiseの配列を返します。

ただし、その最後のwhen()句は実行されず、「DONE」という単語はコンソールに表示されません。 jquery-1.5のソースコードは、オブジェクトが存在しない場合にwhen()が内部Deferred()オブジェクトを作成してリストを管理するため、$。when.apply()に渡すオブジェクトとして「null」が受け入れられることを暗示しているようです渡された。

これはFutures.jsを使用して機能しました。このようになっていない場合、jQuery Deferredの配列をどのように管理する必要がありますか?

    var fetch_schemas, fetch_root;

    fetch_schemas = function(schema_urls) {
        var fetch_one = function(url) {
            return $.ajax({
                url: url,
                data: {},
                contentType: "application/json; charset=utf-8",
                dataType: "json"
            });
        };

        return $.map(schema_urls, fetch_one);
    };

    fetch_root = function() {
        return $.ajax({
            url: BASE_URL,
            data: {},
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        });
    };

    $.when(fetch_root()).then(function(data) {
        var promises = fetch_schemas(data.schema_urls);
        $.when.apply(null, promises).then(function(schemas) {
            console.log("DONE", this, schemas);
        });
    });
130
Elf Sternberg

あなたが探しています

$.when.apply($, promises).then(function(schemas) {
     console.log("DONE", this, schemas);
}, function(e) {
     console.log("My ajax failed");
});

これも機能します(作業の価値のために、壊れたajaxは修正されません)。

$.when.apply($, promises).done(function() { ... }).fail(function() { ... });` 

nullの代わりに$を渡すと、$.when内のthisjQueryを参照します。ソースにとっては問題ではありませんが、nullを渡すよりはましです。

すべての$ .ajaxを$.whenとサンプル works に置き換えることでモックアウトしました

したがって、ajaxリクエストの問題か、fetch_schemasに渡す配列のいずれかです。

196
Raynos

上記の回避策(ありがとう!)は、jQueryがresolve()done()を呼び出すため、遅延オブジェクトのfail()メソッドに提供されたオブジェクトを取り戻す問題に適切に対処しません。配列ではなく、個々のパラメーターを使用したコールバック。つまり、arguments疑似配列を使用して、遅延オブジェクトの配列によって返されるすべての解決/拒否されたオブジェクトを取得する必要があります。

_$.when.apply($, promises).then(function() {
     var schemas=arguments; // The array of resolved objects as a pseudo-array
     ...
};
_

遅延オブジェクトの配列を渡したので、結果の配列を取得することは素晴らしいことです。 Array.sort()などのメソッドを使用できるように、擬似配列ではなく実際の配列を取得することもできます。

これらの問題に対処するwhen.jswhen.all()メソッドに触発されたソリューションを次に示します。

_// Put somewhere in your scripting environment
if (jQuery.when.all===undefined) {
    jQuery.when.all = function(deferreds) {
        var deferred = new jQuery.Deferred();
        $.when.apply(jQuery, deferreds).then(
            function() {
                deferred.resolve(Array.prototype.slice.call(arguments));
            },
            function() {
                deferred.fail(Array.prototype.slice.call(arguments));
            });

        return deferred;
    }
}
_

次のように、コールバックで遅延/約束の配列を渡して、解決/拒否されたオブジェクトの配列を取得するだけです。

_$.when.all(promises).then(function(schemas) {
     console.log("DONE", this, schemas); // 'schemas' is now an array
}, function(e) {
     console.log("My ajax failed");
});
_
53
crispyduck

ES6バージョンのjavascriptを使用している場合、オブジェクトの配列をコンマ区切りの引数に変換するスプレッド演算子(...)があります。

$.when(...promises).then(function() {
 var schemas=arguments; 
};

ES6スプレッド演算子の詳細 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator ここを検索

18
pashaplus

このコードを使用すると拡張されます:

var rawWhen = $.when
$.when = function(promise) {
    if ($.isArray(promise)) {
        var dfd = new jQuery.Deferred()
        rawWhen.apply($, promise).done(function() {
            dfd.resolve(Array.prototype.slice.call(arguments))
        }).fail(function() {
            dfd.reject(Array.prototype.slice.call(arguments))
        })
        return dfd.promise()
    } else {
        return rawWhen.apply($, arguments)
    }
}
0
CALL ME TZ