132

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

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

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

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

これは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);
        });
    });
4

4 に答える 4

198

あなたが探しています

$.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() { ... });` 

内部がを参照するように、$代わりに渡すことをお勧めします。ソースには関係ありませんが、渡すよりはましです。nullthis$.whenjQuerynull

$ .ajaxをすべて置き換えてモックアウトする$.whenと、サンプルが機能します

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

于 2011-02-02T19:35:47.530 に答える
53

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

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

延期された配列を渡したので、結果の配列を取り戻すとよいでしょう。また、のようなメソッドを使用できるように、疑似配列の代わりに実際の配列を取得することもできますArray.sort()

これらの問題に対処するwhen.jsのメソッドに触発されたソリューションは次のとおりです。when.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");
});
于 2013-04-25T06:47:40.893 に答える
18

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

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

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

于 2015-03-28T08:16:49.523 に答える
-1

このコードで拡張する場合:

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)
    }
}
于 2015-06-16T07:10:14.397 に答える