3

Already had a layer in JS which helps Gets and Posts to the server with the following implementations :

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);
    });
};

Using these implementations on DataService layer :

// 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);
};

However we use webapi, wich in some cases, a request depends the result of another request generating a "Pyramid of Doom ". For more elegance of code we are implementing the library Q for asynchronous programming.

To follow the pattern shown above using Q promisses was implemented new method of 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);
    });
};

I'm trying to use this implementation on DataService layer this way:

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

Anyway in my layer viewmodel javascript suppose I need to use 3 finds and one depends on the outcome of the other:

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();

My problem :

I admit that I am not able to implement the right way, because all my functions inside .then() are coming with undefined args.

I wonder know what is the best practice to meet the scenario propose here.

4

1 回答 1

2

我想你会发现 Promise 的吸引力在于你可以用比以前少得多的代码来实现你的目标。不过,您需要了解一些事情。一方面,您不再需要传递或接收回调和错误返回。您只需要确保在处理程序中返回结果或对结果的承诺。这就是值传播到下一个处理程序的方式。

这是您的程序的未经测试的改编,应该说明形式:

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底部的单个调用处理。无论最后是否有错误处理程序,始终以 结束一个链,done()以便之前发生的任何错误,即使是在您的fail处理程序中,也会显示在您的控制台中。

请注意,如果一个操作依赖于前一个操作并且处理程序需要访问第一个和第二个结果,则您只需要嵌套 Promise。如果你只需要第二次操作的结果,你可以链。

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();

您也可以使用 and 来展平事物Q.allpromise.spread但此时我会将您留给文档,因为我希望您了解要点。

于 2013-08-30T22:54:03.867 回答