Promise的认知细节
一、executor函数
Promise新建后executor函数就会立即执行:new Promise( (c, e) => { 立即执行})
二、正常处理
resolve函数用于将Promise状态从pending转变为fulfilled,并将结果值传递给then回调函数。tsconst promise = new Promise((resolve, reject) => { resolve(result); }); promise.then(result => { console.log(result); });resolve(promise):resolve(v)中的v可以是Promise实例。tsconst thenable = new Promise((resolve, reject) => { resolve(result); // or reject(new Error('error')); }); const promise = new Promise((resolve) => { resolve(thenable); }); promise.then(result => { console.log(result); }); promise.catch(error => { console.log(error); });此时
promise的状态由thenable决定,promise自身怎么用resolve,reject都无效了,相当于thenable控制promise的状态:- 当
thenable状态从pending转resolved,那么执行promise.then; - 当
thenable状态从pending转rejected,那么执行promise.catch
- 当
Promise.resolve(promise):由于Promise.resolve(v)等价于new Promise(resolve => resolve(v)),所以Promise.resolve(promise)等价于new Promise(resolve => resolve(promise))。又因为当resolve(v)中的v是Promise实例时,则当前resolve所在的Promise实例的具体状态就由v决定。因此Promise.resolve(promise)的最终状态就由promise决定,Promise.resolve本身在这里只是起到了包装一个参数为Promise实例的作用,并不会影响promise的状态,别被它的名字中带resolve误导了,它不是将当前promise的状态转为resolved。简而言之,resolve(promise)拿到的是promise本身,接下来的行为都由它的状态来决定。实际工程上通常喜欢使用
Promise.resolve(thenable)来包装一个thenable对象,从而确保thenable的then回调送入到微任务队列中执行,而不是立即同步执行。因为一个thenable对象的then方法可能是一个异步操作,也可能是一个同步操作,如果是一个同步操作,那么thenable的then回调会立即执行,此时我们为了统一行为,避免潜在的同步执行导致的问题,通常使用Promise.resolve(thenable)来统一将then回调送入微任务队列等到事件循环的末尾再执行。
三、异常处理
reject函数用于将Promise状态从pending转变为rejected,并将错误信息传递给catch回调函数。tsconst promise = new Promise((resolve, reject) => { reject(new Error('error')); }); promise.catch(error => { console.log(error); });其中
reject(e)中的e是Error实例,会被catch回调函数接收。在
new Promise((c,e) => {…})当中执行抛出错误会令promise状态从pending转rejected,导致走catch回调。常见的抛出错误的方式如下:tslet promise: Promise<void>; // 方式一:直接抛出错误 promise = new Promise(() => { throw new Error('error'); }); // 方式二:使用try...catch捕获错误 promise = new Promise((_, reject) => { try{ throw new Error('error'); } catch(e) { reject(e); } }); // 方式三:使用reject函数 promise = new Promise((_, reject) => { reject(new Error('error')); }); promise.catch(error => { console.log(error); });以上三种方式都会导致
promise状态从pending转rejected,从而走catch回调。