ES6 Promise对象(实例调用方法promise.then/catch/finally、静态方法Promise.resolve/reject/all/race、promise实现源码)

目录

Promise(function(resolve,reject){})

promise对象调用的方法

promise.then(function(res){},function(rej){})

promise.catch(function(){})

promise.finally(function(){})

Promise上定义好的静态方法

Promise.resolve(js)

Promise.reject(js)

Promise.all([p1,p2,...,pn])

Promise.race([p1,p2,...,pn])

超时处理示例

作用

主要原理

例子

Promise实现源码

具体介绍


Promise(function(resolve,reject){})

首先使用需要通过new Promise(function(resolve,reject){}),Promise()构造函数必须接收一个函数,否则会报错,这个函数会有自动接收2个系统赋值的参数,不定义也会在arguments里接收。新建的对象时会运行function中的代码,新建出来的对象中会有2个系统定义的属性,PromiseState初始为pending,通过在function中调用系统传给function的2个参数来修改,调用resolve()后变为fulfilled,调用reject()后变为rejected。该状态只会改变一次即之后如果还有resolve函数和reject函数都会失去作用。无论调用哪个函数,都会继续走完Promise中的function内容,除非代码出现错误。PromiseResult初始为undefined,通过向resolve()和reject()函数中传入参数改变为参数值。

new Promise((res,rej)=>{
    console.log(1);
    res('y');
    console.log(3)
    res('p');
    rej()
}).then((res)=>{console.log(res)})
//1
//3
//y

注意function中代码如果有错误,除resolve()在错误行之前,PromiseState为fulfilled,PromiseResult为undefined;其它情况PromiseState都为rejected,PromiseResult为错误信息。其中throw(str)语句相当于发生了错误,其错误信息为str字符串内容。

promise对象调用的方法

这些方法是定义在Promise.prototype上的方法,可以在控制台中直接通过Promise.prototype打印查看。

promise.then(function(res){},function(rej){})

当新建promise对象的function中内容完全运行完后才会运行then方法,根据promise对象的PromiseState状态执行函数:

当为fulfilled或rejected时,执行第一个或第二个function把PromiseResult传给res或rej。如果执行的函数中没有return新的promise对象,则返回一个新的promise对象,其PromiseResult为返回值,PromiseState为fulfilled;如果返回了新的promise对象,则根据新的对象接收的函数决定PromiseState和PromiseResult的值。注意当不写第二个functin或传入null时,如果promise对象状态位为rejected,那么返回新promise对象的PromiseState和PromiseResult也相同。

当为pending时,不执行任何函数,直接返回一个新的promise对象,PromiseState为pending,PromiseResult为undefined。

promise.catch(function(){})

同promise.then(null,function(rej){})。

promise.finally(function(){})

最后无论怎样都会执行function中内容,返回promise原对象。

Promise上定义好的静态方法

Promise.resolve(js)

相当于new Promise(function(res,rej){res();js};当js为js代码,不同在于js代码如果出错,该语句是会报错,不运行的。当js为字符串时function里为res(js)。

Promise.reject(js)

相当于new Promise(function(res,rej){rej();js};当中js为js代码,不同在于js代码如果出错,该语句是会报错,不运行的。当js为字符串时function里为rej(js)。

Promise.all([p1,p2,...,pn])

接收一个数组,其中p1,p2,...,pn为promise对象,只有p1,p2,...,pn的PromiseState全为fulfilled时,才返回一个PromiseState为fulfilled的新promise对象且此时PromiseResult为一个数组,数组中的每一位是p1,p2,...,pn的PromiseResult。否则为rejected,PromiseResult为p1,p2,...,pn中首先出现PromiseState='rejected'的PromiseResult。

Promise.race([p1,p2,...,pn])

接收一个数组,其中p1,p2,...,pn为promise对象,返回一个新promise对象,它的PromiseState值为p1,p2,...,pn中第一个PromiseState变化的值(变为非pending状态),PromiseResult等于变化的promise对象的PromiseResult值。

超时处理示例

const request = ajax(url);
const timeout = new Promise((res, rej)=>{
  setTimeout(()=>rej(new Error('timeout')),500)
}
Promise.race([request,timeout]).then(value=>{
  console.log(value);
}).catch(error=>{
  console.log(error)
})

作用

用于解决异步回调(回调地狱)问题。

主要原理

Promise对象的then方法是在新建对象Promise()接收的函数完全执行完后才运行。

例子

下面例子能实现First、Second、Third依次输出。注意then方法中要return新的promise对象中包裹Second输出,如果直接then中输出Second,则只能保证First在Second和Third之前输出,无法保证Second和Third的输出顺序,因为then方法只能保证在new Promise接收的function运行完成之后执行,并不能保证then方法中function内容执行和它返回的新promise的对象的then中的function执行顺序。

new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("First");
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("Second");
            resolve();
        }, 4000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});

Promise实现源码

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
  constructor (executor) {
    try {
      executor(this.resolve, this.reject);
    } catch (e) {
      this.reject(e);
    }
  }
  status = PENDING;
  value = undefined;
  reason = undefined;
  successCallback = [];
  failCallback = [];
  resolve = value => {
    if (this.status !== PENDING) return;
    this.status = FULFILLED;
    this.value = value;
    while(this.successCallback.length) {
      this.successCallback.shift()();
    }
  }
  reject = reason => {
    if (this.status !== PENDING) return;
    this.status = REJECTED;
    this.reason = reason;
    while(this.failCallback.length) {
      this.failCallback.shift()();
    }
  }
  // 默认的参数使then方法能不传参情况下向后传递值
  // new promise((res, rej)=>{res(100)}).then().then(v=>{console.log(v)})
  then (successCallback = value => value, failCallback = reason => { throw reason;}) {
    let promise2 = new MyPromise((resolve, reject) =>{
      if (this.status === FULFILLED) {
        try {
          // 为了能拿到promise2的引用,使用setTimeout将下面代码变为异步代码。
          setTimeout(() => {
            let x = successCallback(this.value);
            // 判断x的值时普通值还是promise对象
            // 如果是普通值,直接调用resolve;
            // 如果是promise对象,查看promise对象返回的结果再根据promise对象返回的结果决定调用resolve还是reject;
            this.resolvePromise(promise2, x, resolve, reject);
          },0)
        } catch (e) {
          reject(e);
        }
      } else if (this.status === REJECTED) {
        try {
          setTimeout(() => {
            let x = failCallback(this.reason);
            this.resolvePromise(promise2, x, resolve, reject);
          },0)
        } catch (e) {
          reject(e);
        }
      } else {
        this.successCallback.push(() => {
          try {
            setTimeout(() => {
              let x = successCallback(this.value);
              this.resolvePromise(promise2, x, resolve, reject);
            },0)
          } catch (e) {
            reject(e);
          }
        });
        this.failCallback.push(() => {
          try {
            setTimeout(() => {
              let x = failCallback(this.reason);
              this.resolvePromise(promise2, x, resolve, reject);
            },0)
          } catch (e) {
            reject(e);
          }
        });
      }
    })
    return promise2;
  }
  resolvePromise(promise2, x, resolve, reject) {
    if(promise2 === x) {
      // 情况1报错
      return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
    }
    if(x instanceof MyPromise) {
      x.then(resolve, reject)
    } else {
      resolve(x)
    }
  }
  catch(failCallback) {
    return this.then(undefined, failCallback)
  }
  finally (callback) {
    return this.then(value => {
     return MyPromise.resolve(callback()).then(() => value);
    }, reason => {
      return MyPromise.resolve(callback()).then(() => { throw reason; });
    })
  }
  static resolve(value){
    if (value instanceof MyPromise) {
      return value;
    } else {
      return new MyPromise(resolve => resolve(value))
    }
  }
  static all(array) {
    let result = [];
    let index = 0;
    function addData (key, value, resolve) {
      result[key] = value;
      index++;
      if (index === array.length) {
        // 当所有的promise都返回后再resolve出去。
        resolve(result);
      }
    }
    return new MyPromise((resolve, reject) => {
      for(let i = 0; i < array.length; i++){
        let current = array[i];
        if (current instanceof MyPromise){
            current.then(value => addData(i, value, resolve), reason => reject(reason))
        } else{
          addData(i, array[i], resolve)
        }
      }
    })
  }
}
// 情况1报错
let promise = new Promise((res, rej) => {
  res(100)
});
let p1 = promise.then(value => p1)

具体介绍

Promise的源码实现 - 知乎

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值