promise详解

久未见 提交于 2019-12-10 01:12:03
/** * 浅谈 Promise * 问题:怎么理解的?:Promise是什么,做什么的,有啥问题,有啥解决办法  *//** * 1、Promise是一种异步编程的解决方案,用于解决回调地狱的问题 * 是构造函数,可以理解为是一个容器,里面是异步事件; *//** * 2、 * 特点: *    1、Promise对象的状态不受外界影响,三种状态:pending(初始状态)、fulfilled(成功)、rejected(失败); *    2、状态改变后不再改变,状态不可逆,只能pending到fulfilled,或者pending变成rejected; * 缺点: *    1、无法取消Promise,一旦建立无法取消; *    2、如果不设置回调函数,Promise内容出错,不会反映到外部; *    3、处于pending状态,无法得知是处于了哪一个阶段,是刚开始,还是快结束了; *//** * 3、Promise的方法 && 简单实现 && axios的实现 * Promise.then()、Promise.catch()、Promise.finally() */    // 1、Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象    Promise.resolve('success').then((res) => {        console.log(res); // success    }, (res) => {        // 不会被调用    })    // 2、Promise.reject(reason)方法返回一个带有拒绝原因reason参数的Promise对象    Promise.reject('failed').then((res) => {        // 不会被调用    },(res) => {        console.log(res); // failed    })    // 3、Promise.race(iterable)方法返回一个promise,一旦迭代器中的某个promise解决或者拒绝,返回的promise就会解决或者拒绝    let p1 = new Promise((resolve, reject) => { setTimeout(()=>{resolve('one')}, 1000) })    let p2 = new Promise((resolve, reject) => { setTimeout(()=>{resolve('two')}, 100) })    Promise.race([p1, p2]).then((res) => { console.log(res) });     // two , p2先执行    // 4、Promise.all()方法返回一个Promise实例,接受一个数组(里面都是Promise实例)作为参数,等待所有都成功才会返回成功,或者其中有一个失败则返回失败,且返回该失败的回调;    Promise.all = (promise) => {        return new Promise((resolve, reject) => {            let result = [], index = 0;            if(promise.length === 0){                resolve(result);            }else{                for (let i = 0; i < promise.length; i++) {                    Promise.resolve(promise[i]).then((res) => {                        result[i] = res;                        // 因为then是异步任务,所以需要另加index                        if(++index === promise.length) resolve(result);                    }, error => {                        reject(error);                        return;                    })                }            }        })    }    /**     * Promise 实现 Polyfill     */    class Rpromise {        constructor(excutor) {            this.status = 'pending'; // 实例状态            this.fulfilledCallbacks = []; // 成功状态事件池            this.rejectedCallbacks = []; // 失败状态事件池            this.value = undefined; // 记录resolve和reject时候的参数            const resolve = (result) => {                // 如果不是pending那么状态已经不能更改了                if(this.status === 'pending'){                    this.status = 'resolved';                    this.value = result;                    // 为了避免还没有执行then,成功状态事件池还没有添加这里就同步执行了,因为forEach是同步方法                    // 所以需要把循环事件池处理成异步的,考虑到then也是异步的,所以不仅要将这里处理成异步的                    // 还要这里的异步在then后执行,then是微任务,加定时器变成宏任务,在then后执行                    let time = setTimeout(() => {                        clearTimeout(time);                        // 循环执行成功状态事件池中的事件                        this.fulfilledCallbacks.forEach(item => item(this.value));                    }, 0);                }            }            const reject = (res) => {                if(this.status === 'pending'){                    this.status = 'rejected';                    this.value = res;                    let time = setTimeout(() => {                        clearTimeout(time);                        this.rejectedCallbacks.forEach(item => item(this.value));                    }, 0);                }            }            try {                excutor(resolve, reject);            } catch (error) {                reject(error);            }        }        then(onFulfilled, onRejected){            // 需要链式调用then方法,所以then方法的返回值必须是一个promise的实例,而resolve和reject            // 两个形参则是用来改变返回的这个promise的状态的,因为下一个then中的回调还挂着返回这个promise            // 对象的身上,需要通过控制resolve和reject的执行来控制下一个then中执行的方法            return new Rpromise((resolve, reject) => {                if(this.status === 'resolved'){                    // 向成功状态事件池添加回调,只添加并没有执行,this指向上一个promise实例,                    // 什么时候执行?在调用this的resolve方法时被执行,result就是传进来的this.value                    this.fulfilledCallbacks.push((result) => {                        // 如果then中的方法执行时报错,直接执行返回的promise的reject方法触发下一个then的失败回调执行                        try {                            let res = onFulfilled(result);                            if(res instanceof Rpromise){                                res.then(resolve, reject);                            }else{                                resolve(res);                            }                        } catch (error) {                            reject(error);                        }                    })                }                if(this.status === 'rejected'){                    this.rejectedCallbacks.push((result) => {                        try {                            let res = onRejected(result);                            if(res instanceof Rpromise){                                res.then(resolve, reject);                            }else{                                reject(res)                            }                        } catch (error) {                            reject(error);                        }                    })                }            })         }    }    /**     * 用Promise实现 axios     * 1、创建XMLHttpRequest对象     * 2、使用open函数     * 3、设置onreadystatechange回调     * 4、send请求数据     */    function axios(params) {        const {url, method, data} = params;        return new Promise((resolve, reject) => {            const xhr = new XMLHttpRequest();            xhr.open(method, url);            xhr.onreadystatechange = () => {                if(xhr.readyState !== 4) return;                if(xhr.statue === 200){                    resolve(xhr.response);                }else{                    reject(xhr.statusText);                }            }            xhr.send(data);        })     }   /** * 4、Promise的痛点解决 *    1、无法取消Promise, 使用async/await 可以return终止 *    2、不设置回调出错不会反映到外部,使用async/await 可以每个阶段return Promise.reject(new Error('拒绝')) */    // async声明的函数的返回本质上是一个Promise    // async是一个关键字,表示异步    function timeout(ms) {        return new Promise((resolve, reject) => {            setTimeout(resolve, ms, "finish");        });    }          timeout(2000).then(value => {        console.log("第一层" + value); return timeout(2000);    }).then(value => {        console.log("第二层" + value); return timeout(2000);    }).then(value => {        console.log("第三层" + value); return timeout(2000);    }).then(value => {        console.log("第四层" + value); return timeout(2000);    }).then(value => {        console.log("第五层" + value); return timeout(2000);    }).catch(err => {        console.log(err);    });    // 改用 async    async function asyncTimeSys(){        await timeout(1000);        console.log("第一层异步结束!")        await timeout(1000);        console.log("第二层异步结束!")        await timeout(1000);        console.log("第三层异步结束!")        await timeout(1000);        console.log("第四层异步结束!")        await timeout(1000);        console.log("第五层异步结束!")        return "all finish";    }    asyncTimeSys().then((value)=>{        console.log(value);    });    // 误区 :await并不是是把同步变为异步    // async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,    // 等到触发的异步操作完成,再接着执行函数体内后面的语句    async function async1(){        console.log('async1 start')        await async2();        console.log('async1 end')      }    async function async2(){        console.log('async2')    }    async1();    console.log('i am koala')console.log(timeout())    // async1 start    // async2    // i am koala    // async1 end    // 简单的说,先去执行后面的同步任务代码,执行完成后,    // 也就是表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!