Promise

119 阅读1分钟

解决异步代码的多层嵌套问题 ; 存在兼容性问题,靠编译解决

1.basic usage

let p = new Promise(function (resolve, reject){
    $.ajax({
        url: '/data',
        dataType: 'json',
        success(arr){
            resolve(arr);
        },
        error(err){
            reject(err);
        }
    });
});

p.then(arr=>{alert('成功了'+arr);}, err=>{alert('失败了');});

Promise.all([
    $.ajax({url: 'data/1.txt', dataType: 'json'}),
    $.ajax({url: 'data/2.txt', dataType: 'json'}),
]).then(arr=>{
    alert('成功');
    console.log(arr);
}, err=>{
    alert('失败了');
});

//promise creator
function ajaxPromise(url){
    return new Promise(function (resolve,reject) {
        //do ajax operations
    })
}

2.implement my Promise

/*
    1.创建一个 Promise Class,接收函数 fn(resolve,reject){} 作为参数
    2.在fn中进行异步操作,成功返回则触发 resolve 函数,失败触发 reject 函数
    3.promise instance 状态 state 变化 : pending --> resolved || rejected
    4.通过 then() 将成功和失败回调函数都保存起来
    5.异步返回后,根据返回的成败结果调用所有对应的成败回调函数
*/
class Promise {
    constructor(ajaxFn) {
        this.callbackQueue = [
            // format 
            // {
            //     fn1,  for successful callback
            //     fn2   for failed callback
            // }
        ];
        this.state = "pending"; //default state
        this._success_result = null;
        this._failure_result = null;
        const _this = this;
        //call async operation
        ajaxFn(function (...args) {
            _this.state = "success";
            _this.callbackQueue.forEach(function(callbackObj){
                callbackObj.fn1(...args);
            });
            _this._success_result = args;
        }, function (...args) {
            _this.state = "failure";
            _this.callbackQueue.forEach(function(callbackObj){
                callbackObj.fn2(...args);
            });
            _this._failure_result = args;
        });
    }
	//Promise instance call then(),state maybe changed
    then(fn1, fn2) {
        const state = this.state;
        if(state === "success"){
            fn1(this.success_result);
        }else if(state === "failure"){
            fn2(this.failure_result);
        }else{
            this.callbackQueue.push({
                fn1,fn2
            });
        }
    }

    static all(arr){
        const results = [];
        return new Promise(function(resolve,reject){
            //需按数组中的promise的顺序返回,这种控制异步回调的方式较常用
            let i=0;
            function next(){
                arr[i].then(function(res){
                    results.push(res);
                    i++;
                    if(i === arr.length){
                        resolve(results);
                    }else{
                        next();
                    }
                },reject);
            }
            next();
        });
    }
    
    static race(arr){
        //......
    }
}