赞
踩
目录
添加 resolve、reject、race、all 等方法
Promise 是一种异步编程的解决方案。在异步操作中,callback 会导致回调地狱的问题,Promise 解决了这个问题。
一个 Promise对象有以下三种状态:
Promise对象内部运行的一个变化, 变化如下:
在使用 Promise 时,通常会调用其 then() 方法来处理异步操作的结果,或者调用 catch() 方法来处理出错信息。同时,Promise 还提供了一些静态方法,如 Promise.resolve()、Promise.reject() 等用于快速创建一个 Promise 实例。
(下文所指的规定是指 Promise A+规范)
首先呢,promise 肯定是一个类,我们就用 class 来声明。
- class myPromise{
- // 构造器
- constructor(executor){
- // 成功
- let resolve = () => { };
- // 失败
- let reject = () => { };
- // 立即执行
- executor(resolve, reject);
- }
- }
Promise 有规定:
于是乎,我们获得以下代码
- class myPromise {
- constructor(executor) {
- // 初始化 state 为等待态
- this.state = 'pending'
- // 成功的值
- this.value = undefined
- // 失败的原因
- this.reason = undefined
- let resolve = value => {
- // state 改变 resolve 调用就会失败
- if (this.state === 'pending') {
- // resolve 调用后 state 转化为成功态
- this.state = 'fulfilled'
- }
- // 储存成功的值
- this.value = value
- }
- let reject = reason => {
- // state 改变 reject 调用就会失败
- if (this.state === 'pending') {
- // reject 调用后 state 转化为失败态
- this.state = 'rejected'
- }
- // 储存失败的原因
- this.reason = reason
- }
- // 立即执行 executor,如果 executor 执行报错,直接执行 reject
- try {
- executor(resolve, reject)
- } catch(err) {
- reject(err)
- }
- }
- }
Promise 有一个叫做 then 的方法,里面有两个参数:onFulfilled 和 onRejected,成功有成功的值,失败有失败的原因
- class myPromise {
- constructor(executor){...}
-
- // then 方法有两个参数 onFulfilled 和 onRejected
- then(onFulfilled, onRejected) {
- // 状态为 fulfilled,执行 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,就调用它们
类似于发布订阅,先将 then 里面的两个函数储存起来,由于一个 promise 可以有多个 then,所以存在同一个数组内。
- // 多个 then 的情况
- let p = new Promise();
- p.then();
- p.then();
成功或者失败时,forEach 调用它们
- class myPromise {
- constructor(executor) {
- this.state = 'pending'
- this.value = undefined
- this.reason = undefined
-
- // 成功存放的数组
- this.onResolvedCallbacks = []
- // 失败存放的数组
- this.onRejectedCallbacks = []
-
- let resolve = value => {
- if (this.state === 'pending') {
- this.state = 'fulfilled'
- }
- this.value = value
-
- // 一旦 resolve 执行,调用成功数组的函数
- this.onResolvedCallbacks.forEach(fn => fn());
- }
- let reject = reason => {
- if (this.state === 'pending') {
- this.state = 'rejected'
- }
- this.reason = reason
-
- // 一旦 reject 执行,调用失败数组的函数
- this.onRejectedCallbacks.forEach(fn => fn())
- }
- try {
- executor(resolve, reject)
- } catch(err) {
- reject(err)
- }
- }
-
- then(onFulfilled, onRejected) {
- if (this.state === 'fulfilled') {
- onFulfilled(this.value)
- }
- if (this.state === 'rejected') {
- onRejected(this.reason)
- }
-
- // 状态为 pending 时
- if (this.state === 'pending') {
- // onFulfilled 传入到成功数组
- this.onResolvedCallbacks.push(() => onFulfilled(this.value))
- // onRejected 传入到失败数组
- this.onRejectedCallbacks.push(() => onRejected(this.reason))
- }
- }
- }
我门常常用到 new Promise().then().then(),这就是链式调用,用来解决回调地狱
- let promise2 = new Promise((resolve, reject)=>{})
- 1. 将这个 promise2 返回的值传递到下一个 then 中
- 2. 如果返回一个普通的值,则将普通的值传递给下一个 then 中
规定 onFulfilled() 或 onRejected() 的值,即第一个 then 返回的值,叫做 x,判断 x 的函数叫做 resolvePromise
- class myPromise {
- constructor(executor){...}
-
- then(onFulfilled, onRejected) {
- // 声明返回的 promise2
- let promise2 = new myPromise((resolve, reject) => {
- if (this.state === 'fulfilled') {
- let x = onFulfilled(this.value)
- resolvePromise(promise2, x, resolve, reject)
- }
- if (this.state === 'rejected') {
- let x = onRejected(this.reason)
- resolvePromise(promise2, x, resolve, reject)
- }
- if (this.state === 'pending') {
- this.onResolvedCallbacks.push(() => {
- let x = onFulfilled(this.value)
- resolvePromise(promise2, x, resolve, reject)
- })
- this.onRejectedCallbacks.push(() => {
- let x = onRejected(this.reason)
- resolvePromise(promise2, x, resolve, reject)
- })
- }
- })
- // 返回 Promise,完成链式
- return promise2
- }
- }
规定了一段代码,让不同的 promise 代码互相套用,叫做 resolvePromise
- let p = new Promise(resolve => {
- resolve(0);
- });
- var p2 = p.then(data => {
- // 循环引用,自己等待自己完成,一辈子完不成
- return p2;
- })
- // 处理 x 的值,如果是普通值直接返回,如果是 promise 则返回 x.then 执行的结果
- function resolvePromise(promise2, x, resolve, reject) {
- // 如果 new 出来的 Promise2 和 x 是同一个,循环引用报错
- if (promise2 === x) return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
-
- // 先判断是不是对象或者函数
- if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
- // 调用了成功就不能失败,调用了失败就不能成功,不能多次调用成功或者失败
- let called
- // 内部可能抛出错误
- try {
- // 声明 then = x 的 then 方法
- let then = x.then
- // 如果 then 是函数,就默认是 promise 了
- if (typeof then === 'function') {
- this.call(x, res => {
- // 成功和失败只能调用一个
- if (called) return
- called = true
- // res 可能是一个 promise,递归调用 resolvePromise,直到解析出的值是普通值
- resolvePromise(promise2, res, resolve, reject)
- }, err => {
- // 成功和失败只能调用一个
- if (called) return
- called = true
- // 直接调用 reject 作为失败的结果,并向下传递
- reject(err)
- })
- } else {
- // 如果 then 不是函数,就说明是个普通值,直接返回 x
- resolve(x)
- }
- } catch(err) {
- // 也属于失败,成功和失败只能调用一个
- if (called) return
- called = true
- // 直接调用 reject 作为失败的结果,并向下传递
- reject(err)
- }
- } else {
- // x 是普通值,直接返回
- resolve(x)
- }
- }
- class myPromise {
- constructor(executor) {
- this.state = 'pending'
- this.value = undefined
- this.reason = undefined
-
- this.onResolvedCallbacks = []
- this.onRejectedCallbacks = []
-
- let resolve = value => {
- if (this.state === 'pending') {
- this.state = 'fulfilled'
- }
- this.value = value
-
- this.onResolvedCallbacks.forEach(fn => fn());
- }
- let reject = reason => {
- if (this.state === 'pending') {
- this.state = 'rejected'
- }
- this.reason = reason
-
- this.onRejectedCallbacks.forEach(fn => fn())
- }
-
- try {
- executor(resolve, reject)
- } catch(err) {
- reject(err)
- }
- }
-
- then(onFulfilled, onRejected) {
- // onFulfilled 如果不是函数,忽略 onFulfilled, 直接返回 value
- onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
- // onRejected 如果不是函数,忽略 onRejected, 让它等于一个函数,并且在函数内继续将 err 向下抛出
- onRejected = typeof onRejected === 'function' ? onRejected : err => {throw err}
-
- let promise2 = new Promise((resolve, reject) => {
- if (this.state === 'fulfilled') {
- // 异步
- setTimeout(() => {
- try {
- let x = onFulfilled(this.value)
- resolvePromise(promise2, x, resolve, reject)
- } catch(err) {
- reject(err)
- }
- }, 0)
- }
- if (this.state === 'rejected') {
- // 异步
- setTimeout(() => {
- try {
- let x = onRejected(this.reason)
- resolvePromise(promise2, x, resolve, reject)
- } catch(err) {
- reject(err)
- }
- }, 0)
- }
- if (this.state === 'pending') {
- this.onResolvedCallbacks.push(() => {
- // 异步
- setTimeout(() => {
- try {
- let x = onFulfilled(this.value)
- resolvePromise(promise2, x, resolve, reject)
- } catch(err) {
- reject(err)
- }
- }, 0)
- })
- this.onRejectedCallbacks.push(() => {
- // 异步
- setTimeout(() => {
- try {
- let x = onRejected(this.reason)
- resolvePromise(promise2, x, resolve, reject)
- } catch(err) {
- reject(err)
- }
- }, 0)
- })
- }
- })
- return promise2
- }
- }
- class myPromise {
- constructor(executor) {...}
-
- then(onFulfilled, onRejected) {...}
-
- // Promise 中的 catch 指代的就是 then 没有成功回调的一个别名而已
- catch(errCallback) {
- return this.then(null, errCallback);
- }
- }
- // 无论如何都会执行,把上一个 then 的结果向下传递
- // 如果 finally 中返回了一个 Promise 会等待这个 Promise 执行完成后继续执行
- myPromise.prototype.finally = function(callback) {
- return this.then(val => {
- return Promise.resolve(callback()).then(() => val);
- }, (err) => {
- return Promise.resolve(callback()).then(() => { throw err; });
- });
- };
- // Promise.resolve 会等待里面的 Promise 执行成功
- Promise.resolve = val => {
- return new Promise((resolve) => {
- resolve(val);
- });
- };
-
- // Promise.reject 不会等待参数中的 Promise 执行完毕
- Promise.reject = () => {
- return new Promise((_, reject) => {
- reject(val);
- });
- };
-
- // all 方法表示等待所有的 Promise 全部成功后才会执行回调
- // 如果有一个 Promise 失败则 Promise 就失败了
- Promise.all = promises => {
- return new Promise((resolve, reject) => {
- // 存放结果
- const res = [];
- // 计数,当count 等于 length的时候就resolve
- let count = 0;
- const resolveRes = (index, data) => {
- // 将执行结果缓存在res中
- res[index] = data;
- // 所有子项执行完毕之后,执行resolve 抛出所有的执行结果
- if (++count === promises.length) {
- resolve(res);
- }
- };
- // 循环遍历每一个参数的每一项
- for(let i = 0; i < promises.length; i++) {
- const current = promises[i];
- // 如果当前项是Promise,则返回 then 的结果
- if (isPromise(current)) {
- current.then((data) => {
- resolveRes(i, data);
- }, (err) => {
- reject(err);
- });
- } else {
- resolveRes(i, current);
- }
- }
- });
- }
-
- // race谁是第一个完成的,就用他的结果
- // 如果失败这个 Promise 就失败,如果第一个是成功就是成功
- Promise.race = (promises) => {
- return new Promise((resolve, reject) => {
- for(let i = 0; i < promises.length; i++) {
- let current = promises[i];
- // 如果是一个 promise 继续执行 then
- if (isPromise(current)) {
- current.then(resolve, reject);
- } else {
- // 是普通值则直接 resolve 返回,并终止循环
- resolve(current);
- break;
- }
- }
- });
- }
- // 目前是通过他测试 他会测试一个对象
- // 语法糖
- 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 符不符合 promises A+ 规范
- // Windows 全局安装
- npm i promises-aplus-tests -g
- // Mac 全局安装
- sudo npm i promises-aplus-tests -g
注意⚠️:本文 Promise 已满足基本使用,但还是存在一些问题待改进。。。
参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。