介绍下 promise 的特性、优缺点,内部是如何实现的并动手实现 Promise、Promise.all

1)Promise基本特性

  • 1、Promise有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)
  • 2、Promise对象接受一个回调函数作为参数, 该回调函数接受两个参数,分别是成功时的回调resolve和失败时的回调reject;另外resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;reject的参数通常是一个Error对象的实例。
  • 3、then方法返回一个新的Promise实例,并接收两个参数onResolved(fulfilled状态的回调);onRejected(rejected状态的回调,该参数可选)
  • 4、catch方法返回一个新的Promise实例
  • 5、finally方法不管Promise状态如何都会执行,该方法的回调函数不接受任何参数
  • 6、Promise.all()方法将多个多个Promise实例,包装成一个新的Promise实例,该方法接受一个由Promise对象组成的数组作为参数(Promise.all()方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例),注意参数中只要有一个实例触发catch方法,都会触发Promise.all()方法返回的新的实例的catch方法,如果参数中的某个实例本身调用了catch方法,将不会触发Promise.all()方法返回的新实例的catch方法
  • 7、Promise.race()方法的参数与Promise.all方法一样,参数中的实例只要有一个率先改变状态就会将该实例的状态传给Promise.race()方法,并将返回值作为Promise.race()方法产生的Promise实例的返回值
  • 8、Promise.resolve()将现有对象转为Promise对象,如果该方法的参数为一个Promise对象,Promise.resolve()将不做任何处理;如果参数thenable对象(即具有then方法),Promise.resolve()将该对象转为Promise对象并立即执行then方法;如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为fulfilled,其参数将会作为then方法中onResolved回调函数的参数,如果Promise.resolve方法不带参数,会直接返回一个fulfilled状态的 Promise 对象。需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
  • 9、Promise.reject()同样返回一个新的Promise对象,状态为rejected,无论传入任何参数都将作为reject()的参数

2)Promise优点

  • ①统一异步 API
    • Promise 的一个重要优点是它将逐渐被用作浏览器的异步 API ,统一现在各种各样的 API ,以及不兼容的模式和手法。
  • ②Promise 与事件对比
    • 和事件相比较, Promise 更适合处理一次性的结果。在结果计算出来之前或之后注册回调函数都是可以的,都可以拿到正确的值。 Promise 的这个优点很自然。但是,不能使用 Promise 处理多次触发的事件。链式处理是 Promise 的又一优点,但是事件却不能这样链式处理。
  • ③Promise 与回调对比
    • 解决了回调地狱的问题,将异步操作以同步操作的流程表达出来。
  • ④Promise 带来的额外好处是包含了更好的错误处理方式(包含了异常处理),并且写起来很轻松(因为可以重用一些同步的工具,比如 Array.prototype.map() )。

3)Promise缺点

  • 1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  • 2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  • 3、当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
  • 4、Promise 真正执行回调的时候,定义 Promise 那部分实际上已经走完了,所以 Promise 的报错堆栈上下文不太友好。
  • 5、Promise 只能有一个最终值或一个最终错误,无法同时返回多个值。

实现Promise.all:

function promiseAll(promises) {
  return new Promise(function(resolve, reject) {
    if(!Array.isArray(promises)){
        throw new TypeError(`argument must be a array`)
    }
    var resolvedCounter = 0;
    var promiseNum = promises.length;
    var resolvedResult = [];
    for (let i = 0; i < promiseNum; i++) {
      Promise.resolve(promises[i]).then(value=>{
        resolvedCounter++;
        resolvedResult[i] = value;
        if (resolvedCounter == promiseNum) {
            return resolve(resolvedResult)
          }
      },error=>{
        return reject(error)
      })
    }
  })
}

// test
let p1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve(1)
    }, 1000)
})
let p2 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve(2)
    }, 2000)
})
let p3 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve(3)
    }, 3000)
})
promiseAll([p3, p1, p2]).then(res => {
    console.log(res) // [3, 1, 2]
})

实现 Promise:

下面是一个简单的 Promise 实现,仅包含异步成功和失败的处理:

class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.result = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.result = value;
        this.onFulfilledCallbacks.forEach(callback => callback(value));
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.result = reason;
        this.onRejectedCallbacks.forEach(callback => callback(reason));
      }
    };

    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      const handle = (callback) => {
        try {
          const result = callback(this.result);
          if (result instanceof MyPromise) {
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      };

      if (this.state === 'fulfilled') {
        handle(onFulfilled);
      } else if (this.state === 'rejected') {
        handle(onRejected);
      } else {
        this.onFulfilledCallbacks.push(() => handle(onFulfilled));
        this.onRejectedCallbacks.push(() => handle(onRejected));
      }
    });
  }

  catch(onRejected) {
    return this.then(undefined, onRejected);
  }
}

// 示例用法
const promise = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('Success!');
    // reject('Error!');
  }, 1000);
});

promise
  .then(result => {
    console.log('Fulfilled:', result);
    return result.toUpperCase();
  })
  .then(result => {
    console.log('Modified result:', result);
  })
  .catch(error => {
    console.error('Rejected:', error);
  });

 大厂面试可用

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

const resolvePromise = (promise, x, resolve, reject) => {
  if (x === promise) {
    // If promise and x refer to the same object, reject promise with a TypeError as the reason.
    reject(new TypeError('循环引用'))
  }
  // if x is an object or function,
  if (x !== null && typeof x === 'object' || typeof x === 'function') {
    // If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.
    let called
    try { // If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.
      let then = x.then // Let then be x.then
      // If then is a function, call it with x as this
      if (typeof then === 'function') {
        // If/when resolvePromise is called with a value y, run [[Resolve]](promise, y)
        // If/when rejectPromise is called with a reason r, reject promise with r.
        then.call(x, y => {
          if (called) return
          called = true
          resolvePromise(promise, y, resolve, reject)
        }, r => {
          if (called) return
          called = true
          reject(r)
        })
      } else {
        // If then is not a function, fulfill promise with x.
        resolve(x)
      }
    } catch (e) {
      if (called) return
      called = true
      reject(e)
    }
  } else {
    // If x is not an object or function, fulfill promise with x
    resolve(x)
  }
}

class Promise {
  constructor(executor) {
    this.status = PENDING
    this.value = undefined
    this.reason = undefined
    // 存放成功/失败的队列
    this.onFulfilledCallbacks = []
    this.onRejectedCallbacks = []

    const resolve = (value) => {
      // 如果value是一个Promise 递归解析
      if (value instanceof Promise) {
        return value.then(resolve, reject)
      }
      if (this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        this.onFulfilledCallbacks.forEach(fn => fn())
      }
    }
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        this.onRejectedCallbacks.forEach(fn => fn())
      }
    }
    try {
      executor(resolve, reject) // 立即执行
    } catch (error) {
      reject(error)
    }
  }
  then(onFulfilled, onRejected) {
    // 判断 onFulfilled, onRejected 是否是函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
    let newPromise = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }

        })
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })

      }
      if (this.status === PENDING) {
        this.onFulfilledCallbacks.push((() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(newPromise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        }))
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(newPromise, x, resolve, reject)
            } catch (error) {
              reject(error)
            }
          })
        })
      }
    })
    return newPromise
  }
  /**
   * Promise.catch
   * @description  用于promise方法链示,捕获前面 onFulfilled/onRejected 抛出的异常
   * @param {*} errorCallback 
   */
  catch(errorCallback) {
    return this.then(null, errorCallback)
  }
  /**
   * Promise.finally
   * @description finally 传入的函数 无论成功和失败都执行
   * @param {*} callback 回调函数
   * @returns 返回成功/失败
   */
  finally(callback) {
    return this.then((value) => {
      // 返回上一次的值
      return new Promise(callback()).then(() => value)
    }, error => {
      return new Promise(callback()).then(() => { throw error })
    })
  }
  /**
   * Promise.all
   * @description 当这个数组里的所有promise对象全部变为resolve状态的时候,才会resolve 当有一个promise对象变为reject状态时 直接 reject
   * @param {*} values promise对象组成的数组作为参数
   * @returns 返回一个promise实例
   */
  static all(values) {
    return new Promise((resolve, reject) => {
      let resultArr = []
      let count = 0
      const resultArrByKey = (index, value) => {
        resultArr[index] = value
        if (++count === values.length) {
          resolve(resultArr)
        }
      }
      values.forEach((promise, index) => {
        promise.then((value) => {
          resultArrByKey(index, value)
        }, reject)
      })
    })
  }
  /**
   * Promise.race
   * @description 只要有一个promise对象进入FULFILLED 或者  REJECTED 状态的话,就会继续执行后面的处理
   * @param {*} values  接受promise对象组成的数组作为参数
   * @returns 返回一个Promise实例
   */
  static race(values) {
    return new Promise((resolve, reject) => {
      values.forEach((promise) => {
        promise.then(resolve, reject)
      })
    })
  }
  // 默认产生一个成功的promise
  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value)
    })
  }
  // 默认产生一个失败的promise
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }
}

Promise.deferred = () => {
  let defer = {}
  defer.promise = new Promise((resolve, reject) => {
    defer.resolve = resolve
    defer.reject = reject
  })
  return defer
}

module.exports = Promise

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值