javascript异步的发展史和一步步解析promise源码

299 阅读8分钟

第一部分:javascript异步的发展史

callback -> promise -> generator + co -> async+await(语法糖)

思路:

本地有三个文件,三个文件的中第一个文件存放第二个文件的地址,第二个文件存放第三个文件的地址,第三个文件存放最后的结果,从文件一读取文件二的地址,根据这个地址读取文件三的内容。

准备工作:

我们在本地建立三txt个文件:one.txt里面内容放two.txt、two.txt里面内容放three.txt、three.txt里面放“恭喜你完成了本次的训练!!”

//1、callback(存在回调地狱的问题,导致代码难以维护)

let fs = require("fs");
function getDate(url,callback){
    fs.readFile(url,"utf8",function(err,data){
        callback && callback(data);
    });
};
getDate("one.txt",function(data){
    console.log("1",data);
    getDate(data,function(data){
        console.log("2",data);
        getDate(data,function(data){
            console.log("3",data);
        })
    })
})
//结果
//1 two.txt
//2 three.txt
//3 恭喜你完成了本次的训练!!!

//2、promise

let fs = require("fs");
function getDate(url){
    return new Promise(function(resolve,reject){
        let date = fs.readFile(url,"utf8",function(err,date){
            err ? reject(err) : resolve(date);
        });
    });
}
getDate("one.txt")
    .then(function(success){
        console.log("1",success);
        return getDate(success);
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("2",success);
        return getDate(success);
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("3",success)
    },function(fail){
        console.log("1",fail);
    })
//结果
//1 two.txt
//2 three.txt
//3 恭喜你完成了本次的训练!!!

//3、generator(配合promise使用)

let fs = require("fs");
let bluebird=require("bluebird");
let read=bluebird.promisify(fs.readFile)//使其promise化
function *getDateLast(){
    let date1 = yield read("one.txt","utf8");
    let date2 = yield read(date1,"utf8");
    let date3 = yield read(date2,"utf8");
    let date4 = yield read(date3,"utf8");
}
var content = getDateLast()
    content.next().value.then(function(data){
            console.log("2"+data)
            content.next(data).value.then(function(data){
                console.log("3"+data)
                content.next(data).value.then(function(data){
                    console.log("4"+data)
                });
            });
    });
//结果
//2two.txt
//3three.txt
//4恭喜你完成了本次的训练!!!

//4、async + await(配合promise使用)

let fs=require("fs");
let bluebird=require("bluebird");
let read=bluebird.promisify(fs.readFile);//使其promise化
async function getDate(date){
    let date1=await read(date,"utf8");
    let date2=await read(date1);
    let date3=await read(date2);
    return date3;
}
getDate("one.txt").then(function(success){
    console.log("success"+success)
})
//结果
//success恭喜你完成了本次的训练!!!

第二部分:promise源码解析

1、这里先考虑Promise同步代码,then只有一个的情况

let Promise = require("./Promise");//用自己写的Promise
let fs = require("fs");
function getDate(url){
    return new Promise(function(resolve,reject){
        let date = fs.readFileSync(url,"utf8");
            !date ? reject("失败") : resolve(date);
    });
}
getDate("one.txt")
    .then(function(success){
        console.log("1",success);
    },function(fail){
        console.log("1",fail);
    })

//结果
//1 two.txt

/*思路(这里先考虑Promise同步代码,then只有一个的情况):
 分成两个部分:

Promise+高阶函数和then+2个回调函数,Promise函数的原型上放then;

function Promise(executor){
executor();
}
Promise.prototype.then = function(callback1,callback2){
callback1()
callback2()
}

Promise部分回调函数的参数是两个函数,所以

function Promise(executor){
executor(function(){},function(){});
}
Promise.prototype.then = function(onFulfilled,onRejected){
onFulfilled()
onRejected()
}

Promise负责将计算出的数据存起来,then负责判断传过来的值是成功的还是失败的 Promise部分应该将数据存储在this中,这样执行then的时候可以直接在this上找到数据 then部分判断成功失败的依据应该是Promise部分是执行的成功还是失败,所以Promise部分执行成功失败时要将对应的状态存储到this中

function Promise(executor){
let self = this;
self.value = undefined;
self.reason = undefined;
self.status = "pending";
executor(
function(value){
self.value = value;
self.status = resolved;
},
function(reason){
self.reason = reason;
self.status = rejected;
});
}
Promise.prototype.then = function(onFulfilled,onRejected){
if(self.status === "resolved"){
onFulfilled(resolved)
}
if(self.status === "rejected"){
onRejected(rejected)
}
}

**/

function Promise(executor){
    let self = this;//this将数据在Promise和then之间传递
    //this中添加数据
    self.value = undefined;
    self.reason = undefined;
    self.status = "pending";
    executor(
        function(value){
            self.value = value;
            self.status = "resolved";
        },
        function(reason){
            self.reason = reason;
            self.status = "rejected";
        });
}
Promise.prototype.then = function(onFulfilled,onRejected){
    let self = this//拿到this中的值
    if(self.status === "resolved"){
        onFulfilled(self.value)
    }
    if(self.status === "rejected"){
        onRejected(self.reason)
    }
}
module.exports = Promise;

//2.Prome部分代码异步

let Promise = require("./Promise")
let fs = require("fs");
function getDate(url){
    return new Promise(function(resolve,reject){
        let date = fs.readFile(url,"utf8",function(err,date){
            err ? reject(err) : resolve(date);
        });
    });
}
getDate("one.txt")
    .then(function(success){
        console.log("1",success);
    },function(fail){
        console.log("1",fail);
    })
getDate("two.txt")
    .then(function(success){
        console.log("2",success);
    },function(fail){
        console.log("1",fail);
    })
getDate("three.txt")
    .then(function(success){
        console.log("3",success)
    },function(fail){
        console.log("1",fail);
    })
//结果
//1 two.txt
//2 three.txt
//3 恭喜你完成了本次的训练!!!

/*思路(Promise部分异步函数,then部分一个,支持多个Promise+then): Promise部分执行时有异步代码,所以可能存在Promise还没执行完就走then了, 这时status还是pending状态,所以我们要将执行then时pending状态下的, onFulfilled和onRejected存储到this中,当Promise部分的异步代码走完之前this中有then中要执行的代码, 这时判断状态然后执行相应的then中要执行的代码

  • */
function Promise(executor){
    let self = this;
    self.value = undefined;
    self.reason = undefined;
    self.status = "pending";
    //this上存储then中要执行的函数
    self.onResolvedCallbacks =[];
    self.onRejectedCallbacks =[];
    executor(
        function(value){
            self.value = value;
            self.status = "resolved";
            self.onResolvedCallbacks.forEach(function(fn){//根据条件执行then中的函数
                fn();
            });
        },
        function(reason){
            self.reason = reason;
            self.status = "rejected";
            self.onRejectedCallbacks.forEach(function(fn){//根据条件执行then中的函数
                fn()
            });
        });
}
Promise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    if(self.status === "resolved"){
        onFulfilled(self.value)
    }
    if(self.status === "rejected"){
        onRejected(self.reason)
    }
    if(self.status === "pending"){//存储这个状态要执行的函数,放到一个函数中,当Promise部分调用的时候执行,确保其中的参数是最新的
        self.onResolvedCallbacks.push(function(){onFulfilled(self.value)});
        self.onRejectedCallbacks.push(function(){onRejected(self.reason)});
    }
}
module.exports = Promise;

//3.实现then的链式调用

let Promise = require("./Promise");
let fs = require("fs");
function getDate(url){
    return new Promise(function(resolved,rejected){
        let date = fs.readFile(url,"utf8",function(err,date){
            err ? rejected(err) : resolved(date);
        });
    });
}
getDate("one.txt")
    .then(function(success){
        console.log("1",success);
        return "yy";
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("2",success);
        return "yy";
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("3",success)
    },function(fail){
        console.log("1",fail);
    })
//结果
//1 two.txt
//2 three.txt
//3 恭喜你完成了本次的训练!!!

/*思路(then的链式调用): 执行then时返回一个新的Promise

  • */
function Promise(executor){
    let self = this;
    self.value = undefined;
    self.reason = undefined;
    self.status = "pending";
    self.onResolvedCallbacks =[];
    self.onRejectedCallbacks =[];
    function resolved(value){
        self.value = value;
        self.status = "resolved";
        self.onResolvedCallbacks.forEach(function(fn){
            fn();
        });
    }
    function rejected(reason){
        self.reason = reason;
        self.status = "rejected";
        self.onRejectedCallbacks.forEach(function(fn){
            fn()
        });
    }
    executor(resolved,rejected);

}
Promise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    let promise2;
    if(self.status === "resolved"){
        promise2 = new Promise(function(resolved,rejected){
            onFulfilled(self.value)
        });
    }
    if(self.status === "rejected"){
        promise2 = new Promise(function(resolved,rejected){
            onRejected(self.reason)
        })
    }
    if(self.status === "pending"){
        promise2 = new Promise(function(resolved,rejected){
            self.onResolvedCallbacks.push(function(){
                resolved(onFulfilled(self.value));
            });
            self.onRejectedCallbacks.push(function(){
                rejected(onRejected(self.reason));
            });
        });
    }
    return promise2;//返回一个新的Promise实现了链式调用
}
module.exports = Promise;

//4.promise then部分也是promise

let Promise = require("./Promise")
let fs = require("fs");
function getDate(url){
    return new Promise(function(resolve,reject){
        let date = fs.readFile(url,"utf8",function(err,date){
            err ? reject(err) : resolve(date);
        });
    });
}
getDate("one.txt")
    .then(function(success){
        console.log("1",success);
        return getDate(success);
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("2",success);
        return getDate(success);
    },function(fail){
        console.log("1",fail);
    })
    .then(function(success){
        console.log("3",success)
    },function(fail){
        console.log("1",fail);
    })
//结果
//1 two.txt
//2 three.txt
//3 恭喜你完成了本次的训练!!!

/*思路(then中有promise的情况): 执行then时得到then中Pomise的then的内容然后判断是放到成功还是失败的回调函数中

  • */
function Promise(executor){
    let self = this;
    self.value = undefined;
    self.reason = undefined;
    self.status = "pending";
    self.onResolvedCallbacks =[];
    self.onRejectedCallbacks =[];
    function resolved(value){
        self.value = value;
        self.status = "resolved";
        self.onResolvedCallbacks.forEach(function(fn){
            fn();
        });
    }
    function rejected(reason){
        self.reason = reason;
        self.status = "rejected";
        self.onRejectedCallbacks.forEach(function(fn){
            fn()
        });
    }
    executor(resolved,rejected);

}
function resolvePromise(x,resolved,rejected){
    try{
        let then = x.then;
        if(typeof then === "function"){//x是一个promise
            then.call(x,function(y){
                resolved(y)
            },function(err){//失败
                rejected(err)
            })
        }else{
            resolved(x)
        }
    }catch(e){
        rejected(e)
    }
}
Promise.prototype.then = function(onFulfilled,onRejected){
    let self = this;
    let promise2;
    if(self.status === "resolved"){
        promise2 = new Promise(function(resolved,rejected){
            onFulfilled(self.value)
        });
    }
    if(self.status === "rejected"){
        promise2 = new Promise(function(resolved,rejected){
            onRejected(self.reason)
        })
    }
    if(self.status === "pending"){
        promise2 = new Promise(function(resolved,rejected){
            self.onResolvedCallbacks.push(function(){
                let x = onFulfilled(self.value)
                resolvePromise(x,resolved,rejected)
            });
            self.onRejectedCallbacks.push(function(){
                let x = onRejected(self.reason)
                resolvePromise(x,resolved,rejected)
            });
        });
    }
    return promise2;
}
module.exports = Promise;

//5、最终的得到的代码

function Promise(executor) { // executor是一个执行函数
    let self = this;
    self.status = 'pending';
    self.value = undefined; // 默认成功的值
    self.reason = undefined; // 默认失败的原因
    self.onResolvedCallbacks = []; // 存放then成功的回调
    self.onRejectedCallbacks = []; // 存放then失败的回调
    function resolve(value) { // 成功状态
        if (self.status === 'pending') {
            self.status = 'resolved';
            self.value = value;
            self.onResolvedCallbacks.forEach(function (fn) {
                fn();
            });
        }
    }
    function reject(reason) { // 失败状态
        if (self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
            self.onRejectedCallbacks.forEach(function (fn) {
                fn();
            })
        }
    }
    try {
        executor(resolve, reject)
    } catch (e) { // 捕获的时候发生异常,就直接失败了
        reject(e);
    }
}
function resolvePromise(promise2, x, resolve, reject) {
    // 有可能这里返回的x是别人的promise
    // 尽可能允许其他乱写
    if (promise2 === x) { //这里应该报一个类型错误,有问题
        return reject(new TypeError('循环引用了'))
    }
    // 看x是不是一个promise,promise应该是一个对象
    let called; // 表示是否调用过成功或者失败
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        // 可能是promise {},看这个对象中是否有then方法,如果有then我就认为他是promise了
        try { // {then:1}
            let then = x.then;
            if (typeof then === 'function') {
                // 成功
                then.call(x, function (y) {
                    if (called) return
                    called = true
                    // y可能还是一个promise,在去解析直到返回的是一个普通值
                    resolvePromise(promise2, y, resolve, reject)
                }, function (err) { //失败
                    if (called) return
                    called = true
                    reject(err);
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true;
            reject(e);
        }
    } else { // 说明是一个普通值1
        resolve(x); // 表示成功了
    }
}
Promise.prototype.then = function (onFulfilled, onRjected) {
    //成功和失败默认不穿给一个函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
        return value;
    }
    onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
        throw err;
    }
    let self = this;
    let promise2; //返回的promise
    if (self.status === 'resolved') {
        promise2 = new Promise(function (resolve, reject) {
            // 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
            // x可能是一个promise 也有可能是一个普通的值
            setTimeout(function () {
                try {
                    let x = onFulfilled(self.value);
                    // x可能是别人promise,写一个方法统一处理
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })
        })
    }
    if (self.status === 'rejected') {
        promise2 = new Promise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    let x = onRjected(self.reason);
                    resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            })

        })
    }
    // 当调用then时可能没成功 也没失败
    if (self.status === 'pending') {
        promise2 = new Promise(function (resolve, reject) {
            // 此时没有resolve 也没有reject
            self.onResolvedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onFulfilled(self.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            });
            self.onRejectedCallbacks.push(function () {
                setTimeout(function () {
                    try {
                        let x = onRjected(self.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                })
            });
        })
    }
    return promise2;
}
// 捕获错误的方法
Promise.prototype.catch = function (callback) {
    return this.then(null, callback)
}
// 解析全部方法
// let arr = [];
// arr[1] = 100;
// console.log(arr.length)
Promise.all = function (promises) {
    //promises是一个promise的数组
    return new Promise(function (resolve, reject) {
        let arr = []; //arr是最终返回值的结果
        let i = 0; // 表示成功了多少次
        function processData(index, y) {
            arr[index] = y;
            if (++i === promises.length) {
                resolve(arr);
            }
        }
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(function (y) {
                processData(i, y)
            }, reject)
        }
    })
}
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
    return new Promise(function (resolve, reject) {
        for (var i = 0; i < promises.length; i++) {
            promises[i].then(resolve,reject)
        }
    })
}
// 生成一个成功的promise
Promise.resolve = function(value){
    return new Promise(function(resolve,reject){
        resolve(value);
    })
}
// 生成一个失败的promise
Promise.reject = function(reason){
    return new Promise(function(resolve,reject){
        reject(reason);
    })
}
Promise.defer = Promise.deferred = function () {
    let dfd = {};
    dfd.promise = new Promise(function (resolve, reject) {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd
}
// mjs
module.exports = Promise;