js异步编程

140 阅读2分钟

阶段一 传统callback回调函数

// demo2(回调地域 callback hell)

//callback hell
doSomethingAsync1(function(){
    doSomethingAsync2(function(){
        doSomethingAsync3(function(){
            doSomethingAsync4(function(){
                doSomethingAsync5(function(){
                    // code...
                });
            });
        });
    });
});

阶段二 事件发布/订阅模式

       发布订阅模式,它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行事件监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到

var PubSub = function(){
    this.handlers = {}; 
};
PubSub.prototype.subscribe = function(eventType, handler) {
    if (!(eventType in this.handlers)) {
        this.handlers[eventType] = [];
    }
    this.handlers[eventType].push(handler); //添加事件监听器
    return this;//返回上下文环境以实现链式调用
};
PubSub.prototype.publish = function(eventType) {
    var _args = Array.prototype.slice.call(arguments, 1);
    for (var i = 0, _handlers = this.handlers[eventType]; i < _handlers.length; i++) {
        _handlers[i].apply(this, _args);// 遍历事件监听器
    }
    return this;
};
var event = new PubSub;// 构造PubSub实例
event.subscribe('list', function(msg) {
    console.log(msg);
});
event.publish('list', {data: ['one,', 'two']});// Object {data: Array[2]}

阶段三 Deferred

       jQuery $.Deferred()是一个构造函数,用来返回一个链式实用对象方法来注册多个回调,并且调用回调队列,传递任何同步或异步功能成功或失败的状态。成功回调done()中使用deferred.resolve,失败回调fail()中使用deferred.reject

var deferred = $.Deferred();
$.ajax(url, {
    type: "post",
    dataType: "json",
    data: data
}).done(function(json) [
    if (json.code !== 0) {
        showError(json.message || "操作发生错误");
        deferred.reject();
    } else {
        deferred.resolve(json);
    }
}).fail(function() {
    showError("服务器错误,请稍后再试");
    deferred.reject();
}).always(function() {
    if (button) {
        button.prop("disabled", false);
    }
});
return deferred.promise();

阶段四 Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。   所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。   使用Promise对象可以用同步操作的流程写法来表达异步操作,避免了层层嵌套的异步回调,代码也更加清晰易懂,方便维护,也可以捕捉异常。

function fn(num) {
  return new Promise(function(resolve, reject) {
    if (typeof num == 'number') {
      resolve();
    } else {
      reject();
    }
  })
  .then(function() {
    console.log('第1个then:参数是一个number值');
  })
  .then(null, function() {
    console.log('第2个then');
  })
}
fn('haha');
fn(1234);// 第1个then:参数是一个number值、第2个then