3

次の実装を使用して、サーバーへの Gets および Posts を支援する JS のレイヤーが既にあります。

var getJson = function(url, callback, onError) {
    $.get(url)
    .done(function(data) {
        if(callback != null)
            callback(data);
    })
    .fail (function(error) {
        if(onError != null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

var postJSON = function(url, data, callback, onError) {
    $.ajax({
        url : url ,
        type: "POST" ,
        contentType : "application/json"
        dataType : "json" ,
        date : ko.toJSON(data)
    })
    .done(function(data) {
        if(callback ! = null)
            callback(data);
    })
    .fail(function(error) {
        if(onError ! = null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

これらの実装を DataService レイヤーで使用する:

// Get
var find = function(date, onSuccess , onError) {
   var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
   getJson(url , onSuccess , onError);
};

// Post
var save = function(date, onSuccess , onError) {
    var url = /* url with the Controller and Action */;
    postJSON(url, data, onSuccess, onError);
};

ただし、webapi を使用しますが、場合によっては、リクエストが「Pyramid of Doom」を生成する別のリクエストの結果に依存します。コードをより洗練させるために、非同期プログラミング用のライブラリ Q を実装しています。

Q promisses を使用して上記のパターンに従うために、get as show の新しいメソッドが実装されました。

var getJsonDefer = function(url, callback, onError) {
    return Q.when($.getJSON(url))
    .then (function(data) {
        if(callback ! = null)
            callback(data);
    })
    .fail (function(error) {
        if(onError ! = null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

この実装を DataService レイヤーで次のように使用しようとしています。

// Get
var find = function(date, onSuccess , onError) {
   var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
   return getJsonDefer(url, onSuccess, onError);
};

とにかく、レイヤービューモデルのJavaScriptで、3つの検索を使用する必要があり、1つは他の結果に依存するとします。

var = dataOne { 
    filter: " Filter"
};

findOne(dataOne,
       function(result) {
            return result;
       }
       function(error) {
           throw error;
       })
       .then(function(args) {
            var = datatwo { 
                filter: args
            };

            // Second
            findTwo(datatwo ,
               function(result) {
                    return result;
               }
               function(error) {
                   throw error;
               }
            );
        })
        .then(function(args) {
            var = dataThree { 
                filter: args
            };

            // Third
            findThree(dataThree,
                function(result) {
                    return result;
                }
                function(error) {
                    throw error;
                }
            );
        }).catch(function(error) {
            // Handle any error from all above steps
        })
        .done();

私の問題 :

.then() 内のすべての関数に未定義の引数が付いているため、正しい方法を実装できないことを認めます。

ここで提案されているシナリオを満たすためのベストプラクティスは何ですか。

4

1 に答える 1

2

promise の魅力は、以前よりもはるかに少ないコードで目標を達成できることに気付くと思います。ただし、知っておく必要があることがいくつかあります。1 つは、コールバックとエラーバックをやり取りする必要がなくなることです。ハンドラーで結果または結果の約束を返すことを確認する必要があるだけです。これが、値が次のハンドラーに伝搬される方法です。

これは、テストされていないプログラムの適応であり、次の形式を示す必要があります。

var find = function(data) {
    var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
    return Q($.getJson(url));
};

find({filter: "filter"})
.then(function (firstResult) {
    return find({filter: firstResult})
    .then(function (secondResult) {
        return find({filter: secondResult})
        .then(function (thirdResult) {
            return [firstResult, secondResult, thirdResult];
        });
    });
})
.fail(notifyError)
.done();

どのステージのエラーもfail、一番下の 1 回の呼び出しで処理されることに注意してください。最後にエラー ハンドラーがあるかどうかに関係なく、常にチェーンを終了してdone()、ハンドラー内であっても、以前に発生したエラーがfailコンソールに表示されるようにします。

1 つの操作が前の操作に依存し、ハンドラーが最初と 2 番目の結果の両方にアクセスする必要がある場合にのみ、promise をネストする必要があることに注意してください。2 番目の操作の結果のみが必要な場合は、チェーンするだけです。

find({filter: "filter"})
.then(function (firstResult) {
    return find({filter: firstResult})
})
.then(function (secondResult) {
    return find({filter: secondResult})
    .then(function (thirdResult) {
        return [secondResult, thirdResult];
    });
});
.fail(notifyError)
.done();

Q.allとを使用してフラット化することもできますが、この時点ではドキュメントpromise.spreadに任せます。

于 2013-08-30T22:54:03.867 に答える