1.Promise产生背景及标准

家喻户晓,Promise是ES6引入的新个性,旨在解决回调天堂。上面是一个简略的例子:管制接口调用程序:

apiA-->apiB-->apiC。简单的业务,开发人员会裂开。后生在此向老前辈致敬。

// 回调天堂apiA({    handleSuccess(resA){        apiB({            handleSuccess(resB){                apiC({                    handleSuccess(resC){                    }                })            }        })    }})

因而Promise/A+标准应运而生,ES6的Promise就是遵循标准开发进去的。

2. 同步Promise

浏览标准可得上面几点根本要求:

  1. Promise存在三个状态:pending(期待态)、fulfilled(胜利态)、rejected(失败态)
  2. pending为初始态,并能够转化为fulfilled和rejected
  3. 胜利时,不可转为其余状态,且必须有一个不可扭转的值(value)
  4. 失败时,不可转为其余状态,且必须有一个不可扭转的起因(reason)
  5. new Promise(executor=(resolve,reject)=>{resolve(value)}),resolve(value)将状态置为 fulfilled
  6. new Promise(executor=(resolve,reject)=>{reject(reson)}),reject(reson)将状态置为 rejected
  7. 若是executor运行异样执行reject()
  8. thenable:then(onFulfilled, onRejected)

    1. onFulfilled:status为fulfilled,执行onFulfilled,传入value
    2. onRejected:status为rejected,执行onRejected,传入reason
// 1.Promise存在三个状态:pending(期待态)、fulfilled(胜利态)、rejected(失败态)const STATUS_PENDING = 'pending'const STATUS_FULFILLED = 'fulfilled'const STATUS_REJECTED = 'rejected'class myPromise {  constructor(executor) {      // pending为初始态,并能够转化为fulfilled和rejected    this.status = STATUS_PENDING    this.value = '' // 3    this.reason = '' // 4    let resolve = value => {    // 5.      if (this.status === STATUS_PENDING) {        this.status = STATUS_FULFILLED        this.value = value      }    }    let reject = reason => {    //6.      if (this.status === STATUS_PENDING) {        this.status = STATUS_REJECTED        this.reason = reason      }    }    // 7.    try {      executor(resolve, reject);    } catch (err) {      reject(err);    }  }  // 8.  then(onFulfilled = () => {}, onRejected = () => {}) {      // 8.1    if (this.status === STATUS_FULFILLED) {      onFulfilled(this.value)    }    // 8.2    if (this.status === STATUS_REJECTED) {      onRejected(this.reason)    }  }}new myPromise(resolve => {  console.log('before resolve')  resolve(1)}).then(res => {  console.log(res)})new myPromise((resolve, reject) => {  console.log('before reject')  reject('reject error')}).then(res => {  console.log(res)}, error => {  console.log(error)})

3. 异步Promise

new myPromise(resolve => {  console.log('before resolve')  setTimeout(()=>{      resolve(1)  },1000)}).then(res => {  console.log(res)})

promise的状态只能在resolve或者reject的时候扭转,同步代码执行到then回调的时候promise的状态还是pending,明细不合乎咱们的冀望。

如果换做是你,你会怎么解决这个问题?举个栗子,你正在解决一堆事件(pending状态),而后(then),老板曰: 一秒内做完手上的事来一下我办公室,做不完滚蛋。你怕遗记,个别会用清单记录onResolvedCallbacks = ['做完了手上的事,去老板办公室'],onRejectedCallbacks = ['做不完,滚蛋'],1秒后看实现后果,再根据抉择下一步。

欠缺后的代码如下:参考 前端进阶面试题具体解答

const STATUS_PENDING = 'pending'const STATUS_FULFILLED = 'fulfilled'const STATUS_REJECTED = 'rejected'class myPromise {  constructor(executor) {    this.status = STATUS_PENDING    this.value = ''    this.reason = ''    // 胜利寄存的数组    this.onResolvedCallbacks = [];    // 失败寄存法数组    this.onRejectedCallbacks = [];    let resolve = value => {      if (this.status === STATUS_PENDING) {        this.status = STATUS_FULFILLED        this.value = value        // pending->fulfilled 依照胜利清单执行        this.onResolvedCallbacks.forEach(fn => fn())      }    }    let reject = reason => {      if (this.status === STATUS_PENDING) {        this.status = STATUS_REJECTED        this.reason = reason        // pending->rejected 依照异样清单执行        this.onRejectedCallbacks.forEach(fn => fn());      }    }    try {      executor(resolve, reject);    } catch (err) {      reject(err);    }  }  then(onFulfilled = () => {}, onRejected = () => {}) {    if (this.status === STATUS_FULFILLED) {      onFulfilled(this.value)    }    if (this.status === STATUS_REJECTED) {      onRejected(this.reason)    }    // 繁忙状态,先记录老板嘱咐的内容    if (this.status === STATUS_PENDING) {      // onFulfilled传入到胜利数组      this.onResolvedCallbacks.push(() => onFulfilled(this.value))      // onRejected传入到失败数组      this.onRejectedCallbacks.push(() => onRejected(this.reason))    }  }}// 异步new myPromise((resolve, reject) => {  console.log('老板曰: 一秒做完手上的事来一下我办公室,做不完滚蛋')  setTimeout(() => {    if (false) { // 臣妾做不到啊      resolve('做完了手上的事,去老板办公室')    } else {      reject('做不完,滚蛋')    }  }, 1000)}).then(res => {  console.log(`1s 后:${res}`)}, error => {  console.log(`1s 后:${error}`)})// 老板曰: 一秒做完手上的事来一下我办公室,做不完滚蛋// 1s 后:做不完,滚蛋

4. new Promise().then().then()...

这个思路倒是挺简略,就是then函数返回值为另一个Promise实例。依据标准批改后如下:

const PENDING = 'pending'const FULFILLED = 'fulfilled'const REJECTED = 'rejected'function resolvePromise(promise2, x, resolve, reject) {  // 循环援用报错  if (x === promise2) {    // reject报错    return reject(new TypeError('Chaining cycle detected for promise'));  }  // 避免屡次调用  let called;  // x不是null 且x是对象或者函数  if (x != null && (typeof x === 'object' || typeof x === 'function')) {    try {      // A+规定,申明then = x的then办法      let then = x.then;      // 如果then是函数,就默认是promise了      if (typeof then === 'function') {        // 就让then执行 第一个参数是this   前面是胜利的回调 和 失败的回调        then.call(x, y => {          // 胜利和失败只能调用一个          if (called) return;          called = true;          // resolve的后果仍旧是promise 那就持续解析          resolvePromise(promise2, y, resolve, reject);        }, err => {          // 胜利和失败只能调用一个          if (called) return;          called = true;          reject(err); // 失败了就失败了        })      } else {        resolve(x); // 间接胜利即可      }    } catch (e) {      // 也属于失败      if (called) return;      called = true;      // 取then出错了那就不要在继续执行了      reject(e);    }  } else {    resolve(x);  }}class Promise {  constructor(executor) {    this.state = PENDING    this.value = ''    this.reason = ''    // 胜利寄存的数组    this.onResolvedCallbacks = [];    // 失败寄存法数组    this.onRejectedCallbacks = [];    let resolve = value => {      if (this.state === PENDING) {        this.state = FULFILLED        this.value = value        // pending->fulfilled 依照胜利清单执行        this.onResolvedCallbacks.forEach(fn => fn())      }    }    let reject = reason => {      if (this.state === PENDING) {        this.state = REJECTED        this.reason = reason        // pending->rejected 依照异样清单执行        this.onRejectedCallbacks.forEach(fn => fn());      }    }    try {      executor(resolve, reject);    } catch (err) {      reject(err);    }  }  then(onFulfilled, onRejected) {    // onFulfilled如果不是函数,就疏忽onFulfilled,间接返回value    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;    // onRejected如果不是函数,就疏忽onRejected,扔出谬误    onRejected = typeof onRejected === 'function' ? onRejected : err => {      throw err    };    let promise2 = new Promise((resolve, reject) => {      if (this.state === FULFILLED) {        // 异步解决:        // onRejected返回一个一般的值,失败时如果间接等于 value => value,        // 则会跑到下一个then中的onFulfilled中,        setTimeout(() => {          try {            let x = onFulfilled(this.value);            resolvePromise(promise2, x, resolve, reject);          } catch (e) {            reject(e);          }        }, 0);      };      if (this.state === REJECTED) {        setTimeout(() => {          try {            let x = onRejected(this.reason);            resolvePromise(promise2, x, resolve, reject);          } catch (e) {            reject(e);          }        }, 0);      };      if (this.state === 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;  }}new Promise(resolve => {    console.log(0)    setTimeout(() => resolve(1), 3000)  })  .then(res => {    console.log(res)    return new Promise(resolve => {      console.log(2)      setTimeout(() => {        resolve(3)      }, 3000)    })  })  .then(res => {    console.log(res)  })

5. catch、resolve、reject、race和all

1. catch(非凡的then办法)

catch(fn){    return this.then(null,fn)}

2. resolve(resolve一个值)

Promise.resolve = val => new Promise(resolve=> resolve(val))

3. reject(reject一个值)

Promise.reject = val => new Promise((resolve,reject)=> reject(val))

4. race

Promise.race([p1, p2, p3])外面哪个后果取得的快,就返回那个后果,不论后果自身是胜利状态还是失败状态 。

Promise.race = promises =>  new Promise((resolve, reject) =>    promises.forEach(pro => pro.then(resolve, reject))  )

5. all

Promise.all能够将多个Promise实例包装成一个新的Promise实例。同时,胜利和失败的返回值是不同的,胜利的时候返回的是一个后果数组,而失败的时候则返回最先被reject失败状态的值。

Promise.all = function (promises) {  return new Promise((resolve, reject) => {    let index = 0;    let result = [];    if (promises.length === 0) {      resolve(result);    } else {      function processValue(i, data) {        result[i] = data;        if (++index === promises.length) {          resolve(result);        }      }      for (let i = 0; i < promises.length; i++) {        //promises[i] 可能是一般值        Promise.resolve(promises[i]).then((data) => {          processValue(i, data);        }, (err) => {          reject(err);          return;        });      }    }  });}

本文旨在记录学习过程,通过手打代码加深印象