Promise详解

Promise 是 JS 对象,用于表示一个异步操作的最终完成 (或失败), 及其结果值

  • new Promise((resolutionFunc, rejectionFunc): void =>{ asynchronous operation })
    returns a promise object. The promise object will be “fulfilled/rejected” when either of the functions resolutionFunc or rejectionFunc are invoked (比如resolve(33)直接返回的是fulfilled-promise;而setTimeout(()=>{resolve(33)},1000)直接返回的是pendgin-promise)
    当 resolutionFunc 或 rejectionFunc 函数被调用时,它们分别对应 将 返回的 promise 变成fulfilled or rejected状态 需要执行的函数,接受一个 value 参数,作为.then(cb1,cb2) 的回调参数的入参
    the code within the executor has the opportunity to perform some operation and then reflect the operation’s outcome (If the value is not another Promise object) as either “fulfilled” or “rejected” by terminating with an invocation of either the resolutionFunc or the rejectionFunc, respectively 别看 zh-CN 翻译 误导人
    一个关于 event loop 的要点: ()内参数函数(resolutionFunc, rejectionFunc): void =>{ asynchronous operation } 是同步立即执行从 Promise 对象讲解事件循环机制

promise static property

  • Promise.all(iterableArray) 除 2 种特殊情况(空[]或不含 promise)外返回一个 pending-promise: 所有都成功会触发 fulfilled(res 是数组);否则 rejected 触发第一个失败的 promise 的 reject 回调
  • Promise.any(iterableArray) 除 2 种特殊情况(空[]或不含 promise)外返回一个 pending-promise: 第一个成功会触发 fulfilled(res 是第一个 promise 的 res);都不成功的话才 返回异步失败和一个 AggregateError 对象
  • Promise.race(iterableArray) 返回一个 pending-promise: fulfilled & reject 都对应上第一个非 pending 状态的 promiseItem 的 fulfilled & rejected
  • Promise.allSettled(iterableArray) 返回一个数组,每个 item 对于 iterableArrayItem 的 pending-promise, 例: [ {status: "fulfilled", value: 33}, {status: "rejected", reason: Error: an error} ]
    常用于 批量请求多次 api 的 场景,比如:批量改变 table 多行,每行一个 patch 的 api

  • Promise.resolve(promise / thenable-value / static-value) 返回一个 fulfilled-promise {status: fulfilled, result: static-value / promise / thenable-value}
    例:Promise.resolve('xxxx').then(res=>{ console.log(res) }) // 'xxxx'
    一个常用应用场景是: 当一个 parameter 既可以接受 promise 又可以接受 static-value 的时候就用 Promise.resolve,如 我的一开源项目用到

  • Promise.reject(reason) 返回一个 rejected-promise,例: Promise.reject(new Error('fail')).then(resolved, (result) { console.error(result) }); // Error: fail

promise 实例/原型属性

  • promiseXX.then(onFulfilled, onRejected)
    • 两个函参handler(param: promise.result):any分别对应 this 的状态变化目标值触发的回调,其回调参数都有保底动作,一旦其不是个函数类型,内部会转换成标准
    • 返回值是个 Promise,根据**then()**中的onFulfilled 或 onRejected函数的 return 分几种情况(以下以触发了 onFulfilled 为 assumption):这样就实现了 then 的链式调用
      • handler(param): !Promise: {status: fulfilled, result: resolve()-return-value}
      • handler(param): void: {status: fulfilled, result: undefined}
      • handler(param): throw error: {status: rejected, result: error}
      • handler(param): fulfilled-promise: {status: fulfilled, result: promise's-fulfilled-value}
      • handler(param): rejected-promise: {status: rejected, result: promise's-rejected-value}
      • handler(param): pending-promise: {status: pending, result: promise-fulfilled/rejected-value} // 见例 1
  • promiseXX.catch()
    返回值是 Promise and deals with rejected cases only. 可以部分理解成是 .then(null,onrejected)的别名.
    根据 dot 前的promiseXX的返回值 promise 状态 是否是 rejected 来确定 trigger the catch
    obj.catch(onRejected) 实际上内部调用了 obj.then(undefined, onRejected)),所以使用 catch 的 onRejected 回调参数是 required
    返回的 promise 状态:
    • 如果 catch 被触发了,其返回值 同 .then(_, onRejected) 对 onRejected 的判断逻辑,
    • 否则返回 promiseXX 因为压根没 excute 到 catch 之后的代码
  • promiseXX.finally(): 不管 Promise 对象最后状态如何,都会执行的操作
    返回值是 promiseXX自身。见例 2
    和.then()类似,但是有一个很大的不同点在于:return 的fulfilled/rejected-promiseresult
    应用场景是:do some processing or cleanup once the promise is settled, regardless of its outcome

例 1:

const ppp = new Promise((res, reject) => {
  reject("xx");
}).catch((e) => {
  return new Promise((res) => {
    setTimeout(() => {
      res("aaaa");
    }, 12000);
  });
});
setTimeout(() => {
  console.log(ppp); // Promise {<pending>} { [[PromiseState]]: "pending", [[PromiseResult]]: undefined }
}, 1000);

例 2

const an = new Promise((resolve) => {
  resolve(3);
});
const bb = an.finally(() => {
  console.log(an); // 后 Promise {<fulfilled>}
});
console.log(an, bb, an === bb); // 先 Promise {<fulfilled>}, Promise {<pending>}, false

Promise 相比 callback 解决了什么问题

  • 可靠可信,promise 是原生支持的,相比自己实现的 让第三方函数内部逻辑判断 callback 的方式要可靠,promise 对象的状态 只能单向改变不可逆
  • 多个相关 callback 嵌套的回调地狱,难以管理和 human-readable,promise 通过 .then 将代码 dock 在第一个异步命令上
  • Promise 给 JS 带来了不一样的异步编程方式,但它本质上还是 callback,但是其特点是:
    把一个个异步操作分别封装成合适的返回 Promise 的函数之后,我们可以借助 Promise 的特性来将一个一个异步操作函数组合起来,形成一个 Promise chain,这时才能发挥 Promise 的最大作用
    https://github.com/NevenLeung/blog/issues/1

promise 的 reject 回调和 catch 的区别:

其实 reject 跟 catch 是一个东西,当同步的情况下,无论 throw 还是 reject 都会执行 onRejected 调用。区别在于 throw 不能用于异步调用中
比如new Promise((res,reject)=>{setTimeout(()=>{throw 'xxx'}, 1000)}).catch(funError)不会触发 funError 被 catch 捕获,因为.catch 前的 variable 就永远是个 pending-promise (Promise Constructor 函参压根执行没有resreject
new Promise((res,reject)=>{setTimeout(()=>{reject 'xxx'}, 1000)}).catch(funError)会触发 funError

手写 Promise

https://github.com/Hojondo/utils/blob/master/fake_promise.js


   转载规则


《Promise详解》 Ryan Who 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
localStorage indexDB sessionStorage cookie session token localStorage indexDB sessionStorage cookie session token
cookieHTTP 协议是无状态的,HTTP 协议自身不对请求和响应之间的通信状态进行保存。Cookie 指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。大小限制在 4KB 左右(cookie 每一个 name=v
2021-05-24
下一篇 
函数式编程语言 Haskell 函数式编程语言 Haskell
Haskell 与副作用斗争过程中的一个方式就是使用类型。它将所有的副作用都推进类型系统。 https://www.haskell.org/
2021-05-20
  目录