JavaScript中的异步编程

作者: 心彻 | 来源:发表于2017-06-20 18:19 被阅读92次

    我们在实际开发过程中经常遇到这样的问题:B函数里需要用到的变量或者参数需要A函数执行结束后才能得到。

    var name="";
    function A() {
        $.ajax({
            url: "/api/test",
            type: "post",
            data:JSON.stringify(data),
            dataType: "json",
            contentType:"application/json",
            success: function(data) {
                name=data.name;
            }
        });
    }
    function B(){
        $("#lbl_Name").text(name);
    }
    A();
    B();
    

    但是JavaScript的异步模式让B函数不会等A函数执行结束后再去执行,为了解决这个问题,通常我们有如下几种解决方案。

    1.把B函数放到A函数ajax请求的complete里执行

    代码修改如下:

    var name = "";
    function A() {
        $.ajax({
            url: "/api/test",
            type: "post",
            data: JSON.stringify(data),
            dataType: "json",
            contentType: "application/json",
            success: function(data) {
                name = data.name;
            },
            complete: function() {
                B();
            }
        });
    }
    function B() {
        $("#lbl_Name").text(name);
    }
    A();
    

    2.回调函数

    将B函数作为A函数的入参,代码修改如下:

    var name="";
    function A(callback) {
        $.ajax({
            url: "/api/test",
            type: "post",
            data:JSON.stringify(data),
            dataType: "json",
            contentType:"application/json",
            success: function(data) {
                name=data.name;
                callback&&callback();
            }
        });
    }
    function B(){
        $("#lbl_Name").text(name);
    }
    A(B);
    

    但是回调函数有个坑,叫“回调地狱”或者“代码金字塔”,比如B要等A执行结束,C要等B执行结束,D要等C执行结束,E要等D执行结束,于是便有了“回调地狱”,如下:

    A(B(C(D(E))))
    

    为了解决这个问题,于是有了Promise对象,下面就来说一说,如何使用Promise对象进行异步编程吧。

    3.Promise对象

    代码修改如下:

    var name = "";
    function A(resolve, reject) {
        $.ajax({
            url: "/api/test",
            type: "post",
            data: JSON.stringify(data),
            dataType: "json",
            contentType: "application/json",
            success: function(data) {
                name = data.name;
                resolve();
            }
        });
    }
    function B() {
        $("#lbl_Name").text(name);
    }
    var promise = new Promise(function(resolve, reject) {
        A(resolve, reject)
    });
    promise.then(B);
    

    注:新建Promise对象时,resolve必传,reject可选。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Rejected时调用。
    使用Promise对象时,可以将刚刚的“回调地狱”改写如下:

    var promise = new Promise(function(resolve, reject) {
        A(resolve, reject)
    });
    promise.then(B)
        .then(C)
        .then(D)
        .then(E);
    

    此部分内容的参考文献:
    Promise 对象
    JavaScript Promise迷你书(中文版)

    4.jQuery的Deferred对象

    其实,jQuery的Deferred对象是基于CommonJS Promises/A设计的。具体使用方法如下:

    var name = "",
        dfd = $.Deferred();
    function A(dfd) {
        $.ajax({
            url: "/api/test",
            type: "post",
            data: JSON.stringify(data),
            dataType: "json",
            contentType: "application/json",
            success: function(data) {
                name = data.name;
                dfd.resolve();
            }
        });
        return dfd.promise();
    }
    function B() {
        $("#lbl_Name").text(name);
    }
    A(dfd).then(B);
    

    这段代码有优化的余地,具体详见:
    jQuery的deferred对象详解代码示例8到代码示例9的优化。
    其他参考文献:
    Javascript异步编程的4种方法
    //Add On 21st June Thanks for brucewar's remind


    5.Generator函数

    好吧,这个没吃透,没实现成功。
    参考文献:Generator 函数的语法
    Generator 函数的异步应用

    6.async和await

    实现代码:

    var name = "";
    function A() {
        $.ajax({
            url: "/api/test",
            type: "post",
            data: JSON.stringify(data),
            dataType: "json",
            contentType: "application/json",
            success: function(data) {
                name = data.name;
            }
        });
    }
    function B() {
        $("#lbl_Name").text(name);
    }
    var f=async function asyncFun() {
            await A();
            await B();
        }
        f();
    

    参考文章:async 函数

    相关文章

      网友评论

        本文标题:JavaScript中的异步编程

        本文链接:https://www.haomeiwen.com/subject/hbxaqxtx.html