【问题标题】:Best practices for implementing asynchronous javascript programming with promise Q library使用 promise Q 库实现异步 javascript 编程的最佳实践
【发布时间】:2013-09-03 09:14:05
【问题描述】:

已经在 J​​S 中有一个层,它通过以下实现帮助获取和发布到服务器:

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,在某些情况下,一个请求取决于另一个请求的结果,生成一个“末日金字塔”。 为了使代码更优雅,我们正在实现用于异步编程的库 Q。

为了遵循上面显示的模式,使用 Q Promises 实现了新的 get 方法,如下所示:

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

无论如何,在我的层 viewmodel javascript 中,假设我需要使用 3 个查找,其中一个取决于另一个的结果:

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() 中的所有函数都带有未定义的参数。

我想知道满足此处提出的方案的最佳做法是什么。

【问题讨论】:

    标签: javascript asynchronous asp.net-web-api deferred q


    【解决方案1】:

    我想你会发现 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();
    

    您也可以使用 Q.allpromise.spread 将事物展平,但此时我会将您留给 documentation,因为我希望您明白要点。

    【讨论】:

    • 非常感谢克里斯。 “您只需要确保在处理程序中返回结果或对结果的承诺。这就是值传播到下一个处理程序的方式。”这就是“诀​​窍”。 Javascript 及其实现每天都让我着迷。是的,我将继续学习以提高我的知识。
    猜你喜欢
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 2013-02-02
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多