Js
异步与构造函数
为什么不在 constructor 中使用异步?https://stackoverflow.com/questions/43431550/async-await-class-constructor#answer-52431905
为什么不在 React 的组件构造函数中获取数据?https://stackoverflow.com/a/38913497/14602831
首先,构造函数不可以是一个 async 函数:
也就是 构造函数只能返回一个纯对象
其次,构造函数中是可以 异步设置 this 的,但似乎没什么意义:
React 其实也可以在构造函数中获取数据,但依旧需要 setState 才能生效,异步后修改 this.state 是无法触发渲染的。
而之前之所以约定俗成的说一定要在 didMount 中调用是因为,早期 React 存在 bug,非didMount 中的 setState 有一定几率不响应。
那如果一定要用 async 来构造一个东西
创建一个 builder:
实例只可从 build 函数中创建,此时相当于在 new 操作前植入一段异步处理
class myClass {
constructor (async_param) {
if (typeof async_param === 'undefined') {
throw new Error('Cannot be called directly');
}
}
static async build () {
var async_result = await doSomeAsyncStuff();
return new myClass(async_result);
}
}
从这里也能看出来整个流程是静态的。即使使用 builder ,此时的创建流程也依旧是无法干涉 实例的。
还有一种臊皮的操作:
通过匿名函数立即执行(IEFES)
class AsyncConstructor {
constructor() {
return (async () => {
// All async code here
this.value = await asyncFunction();
return this; // when done
})();
}
}
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
利用参数类型为元组,函数提供泛型接口,即可实现参数的可拓展:
type Arr = readonly unknown[];
function partialCall<T extends Arr, U extends Arr, R>(
f: (...args: [...T, ...U]) => R,
...headArgs: T
) {
return (...tailArgs: U) => f(...headArgs, ...tailArgs);
}
所以 React 的 props 类型也同理:
type Origin = [number]
interface Props<T extends any[]> {
fn: (...args: [...Origin, ...T]) => void
}
使用时推导如下: