Promise

Promise 是异步编程的一种解决方案

如何理解:
没有异步就不需要promise。
Promise本身不是异步,只是我们去编写异步代码的一种方式

1,声明一个Promise
首先呢,promise肯定是一个类,我们就用class来声明。

由于new Promise((resolve, reject)=>{}),所以传入一个参数(函数), promisesA+规范 里叫他executor(执行器),传入就执行。

executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
由于resolve和reject可执行,所以都是函数,我们用let声明。

创建一个Promise类
在这里插入图片描述
2,解决基本状态

promiseA+规范对Promise有规定:

Promise存在三个状态(status)pending、fulfilled、rejected
pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
成功时,不可转为其他状态,且必须有一个不可改变的值(value)
失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
成功态 : new Promise((resolve,reject)=>{resolve(value)})
resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
失败态 : new Promise((resolve, reject)=>{reject(reason)})
reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
若是executor函数报错, 直接执行reject(); 既抛出一个错误:throw new Error()

**手写一个最基本的promise类**

//首先设置三个状态(status)pending、fulfilled、rejected
const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";

class Promise {
     //给创造函数中传入执行器executor
    constructor(executor) {
        this.status = PENDING  // 初始化status为等待态
        this.value = undefined //终值
        this.reason = undefined //据因
        let resolve = (value) => {    //成功的函数
            if (this.status == PENDING) {
                // 储存成功的值
                this.value = value
                // resolve调用后,status转化为成功态
                this.status = RESOLVED
            }
        }
        let reject = (reason) => {    //失败的函数
            if (this.status == PENDING) {
                // 储存失败的值
                this.reason = reason
                // reject 调用后,status转化为失败态
                this.status = REJECTED
            }
        }
        // 看有没有弹出错误
        try{
            //没有抛出错误,执行executor
            executor(resolve,reject)
        }catch(e){   //如果抛出错误,拿到抛出的数据e
            reject(e)  //遇到抛出错误直接执行reject
        }
    }
    // then函数  当.then时调用
    //调用then函数要传入两个函数(--(data)=>{}---(err)=>{}--),即onfulfilled(成功时调用),onrejected(失败时调用)
    then(onfulfilled,onrejected){
        if(this.status===RESOLVED){
            // 成功态调用的函数
            onfulfilled(this.value)
        }
        if(this.status===REJECTED){
            // 失败态调用的函数
            onrejected(this.reason)
        }
    }
}
module.exports = Promise

3,then方法

Promise规定:Promise有一个叫做then的方法,里面有两个参onFulfilled,onRejected,成功有成功的值,失败有失败的原因

当状态status为fulfilled,则执行onFulfilled,传入this.value。当状态status为rejected,则执行onRejected,传入this.reason
onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数

class Promise{
  constructor(executor){...}
  // then 方法 有两个参数onFulfilled onRejected
  then(onFulfilled,onRejected) {
    // 状态为fulfilled(即resolve),执行onFulfilled,传入成功的值
    if (this.state === 'fulfilled') {
      onFulfilled(this.value);
    };
    // 状态为rejected,执行onRejected,传入失败的原因
    if (this.state === 'rejected') {
      onRejected(this.reason);
    };
  }
}

现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then时state还是pending等待状态
我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
接下来就看一下异步的解决方案

4,解决异步,完成resolvePromise函数

类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。

 // 多个then的情况
let p = new Promise();
p.then();
p.then();

成功或者失败时,forEach调用它们

	const PENDING = "PENDING";
	const RESOLVED = "RESOLVED";
	const REJECTED = "REJECTED";
	
	class Promise {
	    constructor(executor) {
	        this.status = PENDING
	        this.value = undefined //终值
	        this.reason = undefined //据因
	        // 有异步的时候才存回调函数
	        this.onResolvedCallbacks=[]  //存成功的回调函数,相当于一个容器
	        this.onRejectedCallbacks=[]  //存失败的回调函数,相当于一个容器
	        let resolve = (value) => { //成功的函数
	            if (this.status == PENDING) {
	                this.value = value
	                this.status = RESOLVED
	                //当是成功态时将onResolvedCallbacks中的函数拿出来执行
	                //fn表示onResolvedCallbacks中的每一项
	                this.onResolvedCallbacks.forEach(fn=>fn())
	            }
	        }
	        let reject = (reason) => {  //失败的函数
	            if (this.status == PENDING) {
	                this.reason = reason
	                this.status = REJECTED
	                 //当是失败态时将onRejectedCallbacks中的函数拿出来执行
	                //fn表示onRejectedCallbacks中的每一项
	                this.onRejectedCallbacks.forEach(fn=>fn())
	            }
	        }
	        // 看有没有弹出错误
	        try{
	            executor(resolve,reject)
	        }catch(e){
	            reject(e)
	        }
	    }
	    // then函数
	    then(onfulfilled,onrejected){
	        if(this.status===RESOLVED){
	            // 成功态调用的函数
	            onfulfilled(this.value)
	        }
	        if(this.status===REJECTED){
	            // 失败态调用的函数
	            onrejected(this.reason)
	        }
	        // 如果调用then的时候,状态是等待态,表示可能存在异步
	        if(this.status===PENDING){
	            // 订阅  将成功的函数放入onResolvedCallbacks容器中
	            this.onResolvedCallbacks.push(()=>{
	                onfulfilled(this.value)
	            })
	            // 订阅   将失败的函数放入onRejectedCallbacks容器中
	            this.onRejectedCallbacks.push(()=>{
	                onrejected(this.reason)
	            })
	        }
	    }
	}
	
	module.exports = Promise

5.**解决then的链式调用**


const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";

// 比较promise2和x的关系
function resolvePromise(promise2, x, resolve, reject) {
    // console.log(promise2)
    // console.log(x)
    // promise2===x相当于 let promise2 = new Promise((resolve)=>{resolve()}).then(data=>{return promise2})
    //就是我在等我吃饭
    if (promise2 === x) {
        // 循环引用报错
        return reject(new TypeError('Chaining cycle detected for promise #<Promise></Promise>'))
    }
    // 防止多次调用
    let called;
    if ((typeof x === "object" && x !== null) || typeof x === "function") {
        // x是一个对象(不包含null)或是一个函数
        try {
            //有可能手动在x上加上一个then属性
            let then = x.then
            if (typeof then === "function") {
                // 防止多次调用
                if (called) return;
                called = true
                // x有then,并且是一个then函数,说明x是promise
                // x是promise
                // 让x调用then方法
                then.call(x, y => {
                    // 采用promise的成功结果,向下传递
                    // resolve(y)
                    // 有可能成功的函数也返回一个promise  递归
                    resolvePromise(promise2, y, resolve, reject)
                }, r => {
                    if (called) return;
                    called = true
                    // 采用promise的失败结果,向下传递
                    reject(r)
                })
            } else {
                // x有then,但then不是一个函数,是一个对象
                // x不是promise,是普通值
                resolve(x)
            }
        } catch (e) {
            reject(e)
        }
    } else {
        // x就是一个普通值
        resolve(x)
    }
}

class Promise {
    constructor(executor) {
        this.status = PENDING
        this.value = undefined //终值
        this.reason = undefined //据因
        // 有异步的时候才存回调函数
        this.onResolvedCallbacks = [] //存成功的回调函数
        this.onRejectedCallbacks = [] //存失败的回调函数
        let resolve = (value) => { //成功的函数
            if (this.status == PENDING) {
                this.value = value
                this.status = RESOLVED
                this.onResolvedCallbacks.forEach(fn => fn())
            }
        }
        let reject = (reason) => { //失败的函数
            if (this.status == PENDING) {
                this.reason = reason
                this.status = REJECTED
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        }
        // 看有没有弹出错误
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }
    // then函数
    then(onfulfilled, onrejected) {
        // 防止then中什么都不写
        // onFulfilled如果不是函数,就忽略onFulfilled,直接返回value
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        // onRejected如果不是函数,就忽略onRejected,直接扔出错误
        onRejected = typeof onRejected === 'function' ? onRejected : err => {
            throw err
        };
        // 这里的promise2是自己写的promise
        // promise2是返回的新的promise
        let promise2 = new Promise((resolve, reject) => {
            if (this.status === RESOLVED) {
                // 因为new完之后才会得到promise2,所以这里用计时器,异步,new完后拿到promise2
                setTimeout(() => {
                    try {
                        // 成功态调用的函数
                        // x可能是promise,也可能是普通值
                        // 如果是普通值,这个值就作为下一个then成功的结果
                        let x = onfulfilled(this.value)
                        // 假如x是promise(有自己的状态),需要让promise2拥有x同样的状态
                        // resolvePromise函数,处理promise2和x之间的关系
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        // 失败态调用的函数
                        let x = onrejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            // 如果调用then的时候,状态是等待态,表示可能存在异步
            if (this.status === PENDING) {
                // 订阅
                this.onResolvedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onfulfilled(this.value)
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
                // 订阅
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onrejected(this.reason)
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
            }
        })

        return promise2
    }
}

module.exports = Promise

6.验证我们的promise是否正确

1、先在后面加上下述代码
2、npm 有一个promises-aplus-tests插件 npm i promises-aplus-tests -g 可以全局安装 mac用户最前面加上sudo
3、命令行 promises-aplus-tests [js文件名] 即可验证

// 目前是通过他测试 他会测试一个对象 // 语法糖 Promise.defer = Promise.deferred =
function () { let dfd = {} dfd.promise = new
Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject; }); return dfd; } module.exports = Promise;
//npm install promises-aplus-tests 用来测试自己的promise符不符合promisesA+规范

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值