记录一下几个Promise知识点

1、简单介绍下Promise。

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数解决回调地狱。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。(当然了也可以简单介绍promise状态,有什么方法,callback存在什么问题等等)

2、实现一个简单的,支持异步链式调用的Promise类。

// [[Resolve]](promise2, x)函数
  resolvePromise(promise2, x, resolve, reject) {
    let called = false;

    if (promise2 === x) {
      return reject(new TypeError('Chaining cycle detected for promise!'))
    }
    
    // 如果x仍然为Promise的情况
    if (x instanceof Promise) {
      // 如果x的状态还没有确定,那么它是有可能被一个thenable决定最终状态和值,所以需要继续调用resolvePromise
      if (x.status === 'pending') {
        x.then(function(value) {
          resolvePromise(promise2, value, resolve, reject)
        }, reject)
      } else { 
        // 如果x状态已经确定了,直接取它的状态
        x.then(resolve, reject)
      }
      return
    }
  
    if (x !== null && (Object.prototype.toString(x) === '[object Object]' || Object.prototype.toString(x) === '[object Function]')) {
      try {
        // 因为x.then有可能是一个getter,这种情况下多次读取就有可能产生副作用,所以通过变量called进行控制
        const then = x.then 
        // then是函数,那就说明x是thenable,继续执行resolvePromise函数,直到x为普通值
        if (typeof then === 'function') { 
          then.call(x, (y) => { 
            if (called) return;
            called = true;
            this.resolvePromise(promise2, y, resolve, reject);
          }, (r) => {
            if (called) return;
            called = true;
            reject(r);
          })
        } else { // 如果then不是函数,那就说明x不是thenable,直接resolve x
          if (called) return ;
          called = true;
          resolve(x);
        }
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }
    } else {
      resolve(x);
    }
  }

3、Promise.then在Event Loop中的执行顺序。

JS中分为两种任务类型:macrotaskmicrotask,其中macrotask包含:主代码块,setTimeoutsetIntervalsetImmediate等(setImmediate规定:在下一次Event Loop(宏任务)时触发);microtask包含:Promiseprocess.nextTick等(在node环境下,process.nextTick的优先级高于PromiseEvent Loop中执行一个macrotask任务(栈中没有就从事件队列中获取)执行过程中如果遇到microtask任务,就将它添加到微任务的任务队列中,macrotask任务执行完毕后,立即执行当前微任务队列中的所有microtask任务(依次执行),然后开始下一个macrotask任务(从事件队列中获取)

4、阐述Promise的一些静态方法。

Promise.allPromise.racePromise.resolvePromise.reject

5、Promise存在哪些缺点

1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。

2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。

3、吞掉错误或异常,错误只能顺序处理,即便在Promise链最后添加catch方法,依然可能存在无法捕捉的错误(catch内部可能会出现错误)

4、阅读代码不是一眼可以看懂,你只会看到一堆then,必须自己在then的回调函数里面理清逻辑。

6、使用Promise进行顺序(sequence)处理。

1、使用async函数配合await或者使用generator函数配合yield

2、使用promise.then通过for循环或者Array.prototype.reduce实现。

function sequenceTasks(tasks) {
    function recordValue(results, value) {
        results.push(value);
        return results;
    }
    var pushValue = recordValue.bind(null, []);
    return tasks.reduce(function (promise, task) {
        return promise.then(() => task).then(pushValue);
    }, Promise.resolve());
}

7、如何停止一个Promise链?

在要停止的promise链位置添加一个方法,返回一个永远不执行resolve或者rejectPromise,那么这个promise永远处于pending状态,所以永远也不会向下执行thencatch了。这样我们就停止了一个promise链。

    Promise.cancel = Promise.stop = function() {
      return new Promise(function(){})
    }

8、Promise链上返回的最后一个Promise出错了怎么办?

catchpromise链式调用的末尾调用,用于捕获链条中的错误信息,但是catch方法内部也可能出现错误,所以有些promise实现中增加了一个方法donedone相当于提供了一个不会出错的catch方法,并且不再返回一个promise,一般用来结束一个promise链。

 done() {
    this.catch(reason => {
      console.log('done', reason);
      throw reason;
    });
  }

9、Promise存在哪些使用技巧或者最佳实践?

1、链式promise要返回一个promise,而不只是构造一个promise

2、合理的使用Promise.allPromise.race等方法。

3、在写promise链式调用的时候,then方法不传onRejected函数,只需要在最末尾加一个catch()就可以了,这样在该链条中的promise发生的错误都会被最后的catch捕获到。如果catch()代码有出现错误的可能,需要在链式调用的末尾增加done()函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值