代码
避免 Promise.all 使用
- Promise.all: 彼此相互依赖或者在其中任何一个reject时立即结束。
- Promise.allSettled: 所有给定的 promise 都已经 fulfilled 或 rejected 后的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果。
示例:
constpromise1=Promise.resolve(3); constpromise2=newPromise((resolve, reject) =>setTimeout(reject, 100, 'foo')); constpromises= [promise1, promise2]; Promise.allSettled(promises). then((results) =>results.forEach((result) =>console.log(result.status))); // expected output:// "fulfilled"// "rejected"
目前大部分 Promise.all 使用的场景下,是多个任务并行执行,其中某个失败了也依然需要保证其他任务执行完毕。
p.s. 如果并发任务中有外部请求(如 HTTP Request、数据库查询连接创建等),不要用 Promise.allSettled, 而要自行封装 Promise.parallel 或者使用队列、Pooling(池)等方式去优化处理。
Async / Await 语法糖优化
// 没必要的 async / awaitasyncfunctiondemo1(): Promise<any> { // 如果方法体内 没有 await 语法糖, 则不需要添加 async// 即便 return 方法为一个 Promise 返回值,也不需要添加 asyncreturnawaitsomeService.somePromiseFunction(); // 如果方法体内 只在 return 部分有一个 await,建议优化掉, 去掉 await 和方法体上的 async}
不要让 await
语句参与运算:
// Bad:someArray.push(awaitsomeFunction()); constsomeObj= { result: awaitsomeFunction() }; // Good:constresult=awaitsomeFunction(); someArray.push(result); constresult=awaitsomeFunction(); constsomeObj= { result};
使用 RxJS 封装底层方法
学习教程: http://rx.js.cool/
贡献仓库: https://github.com/willin/rx.js.cool
适用场景介绍
前端组件
- 如绑定鼠标移动事件并进行计算和处理
- 如绑定鼠标点击事件并设置最小触发间隔
- 侦听屏幕滚动并且 debounce
- 等等
示例:
- 解锁手势: https://stackblitz.com/edit/rxjs-lockscreen?file=index.ts
- 扫雷游戏: https://stackblitz.com/edit/rxjs-minesweeper?file=index.ts
需要可撤销的业务场景
参考: http://rx.js.cool/mixin/undo
流式处理(流程化的方法)
示例:
from(Promise.resolve([ // 模拟数据 { id: 1, name: 'Kitty1', age: 1, breed: 'string' }, { id: 2, name: 'Kitty2', age: 1, breed: 'string' }, { id: 3, name: 'Kitty3', age: 1, breed: 'string' }, { id: 4, name: 'Kitty4', age: 2, breed: 'string' }, { id: 5, name: 'Kitty5', age: 2, breed: 'string' }, { id: 6, name: 'Kitty6', age: 2, breed: 'string2' } ])).pipe( // 此处仅用于作为 rxjs 的操作示例// Filter by AgemergeMap((cats: Cat[]) =>iif( // () =>age>=0, // Query 里的数值类型,如果没有默认值,实际为字符串类型of(cats.filter((cat) =>`${cat.age}`===`${age}`)), of(cats) ) ), // Filter by NamemergeMap((cats: Cat[]) =>iif( // () =>name!=='', of(cats.filter((cat) =>cat.name===name)), of(cats) ) ), // Filter by BreedmergeMap((cats: Cat[]) =>iif( // () =>breed!=='', of(cats.filter((cat) =>cat.breed===breed)), of(cats) ) ), // PaginationmergeMap((cats: Cat[]) =>of(cats.slice(offset, offset+limit))) );
Promise 方法改写
给出几种示例,更多需要自行摸索:
// 示例1:import { from } from'rxjs'; // getPromise() is called once, the promise is passed to the Observableconstobservable$=from(getPromise()); // 示例2:import { defer } from'rxjs'; // getPromise() is called every time someone subscribes to the observable$constobservable$=defer(() =>getPromise());