Js

异步与构造函数

为什么不在 constructor 中使用异步?https://stackoverflow.com/questions/43431550/async-await-class-constructor#answer-52431905
为什么不在 React 的组件构造函数中获取数据?https://stackoverflow.com/a/38913497/14602831
首先,构造函数不可以是一个 async 函数:
也就是 构造函数只能返回一个纯对象
image.png
其次,构造函数中是可以 异步设置 this 的,但似乎没什么意义:
image.png
React 其实也可以在构造函数中获取数据,但依旧需要 setState 才能生效,异步后修改 this.state 是无法触发渲染的。
而之前之所以约定俗成的说一定要在 didMount 中调用是因为,早期 React 存在 bug,非didMount 中的 setState 有一定几率不响应。

那如果一定要用 async 来构造一个东西
创建一个 builder:
实例只可从 build 函数中创建,此时相当于在 new 操作前植入一段异步处理

  1. class myClass {
  2. constructor (async_param) {
  3. if (typeof async_param === 'undefined') {
  4. throw new Error('Cannot be called directly');
  5. }
  6. }
  7. static async build () {
  8. var async_result = await doSomeAsyncStuff();
  9. return new myClass(async_result);
  10. }
  11. }

从这里也能看出来整个流程是静态的。即使使用 builder ,此时的创建流程也依旧是无法干涉 实例的。
还有一种臊皮的操作:
通过匿名函数立即执行(IEFES)

  1. class AsyncConstructor {
  2. constructor() {
  3. return (async () => {
  4. // All async code here
  5. this.value = await asyncFunction();
  6. return this; // when done
  7. })();
  8. }
  9. }
  10. let instance = await new AsyncConstructor();

当然此处 super 无法在 async 中执行,Ts也因为各种问题无法通过。但可以用
https://gist.github.com/vipulwairagade/a77bdd85909d61e3f7d87f2dcc57f2b1

Typescript

元组拓展/可拓展泛型参数

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html
利用参数类型为元组,函数提供泛型接口,即可实现参数的可拓展:

  1. type Arr = readonly unknown[];
  2. function partialCall<T extends Arr, U extends Arr, R>(
  3. f: (...args: [...T, ...U]) => R,
  4. ...headArgs: T
  5. ) {
  6. return (...tailArgs: U) => f(...headArgs, ...tailArgs);
  7. }

所以 React 的 props 类型也同理:

  1. type Origin = [number]
  2. interface Props<T extends any[]> {
  3. fn: (...args: [...Origin, ...T]) => void
  4. }

使用时推导如下:
image.png