mth*_*ers 4 async-await typescript reactjs
我使用create-react-app创建了一个带有 React 和 Typescript 的 Web 应用程序。它使用了一个相当繁重的第三方库。我想通过使用动态导入表达式从主包中排除它。
所以,import { Component } from 'library'
我没有做,而是创建了一个看起来像这样的小包装器:
const loadLibrary = async () => {
const x = await import('library').then((r) => r);
return x;
};
const {
Component,
} = loadLibrary() as any;
// tslint:disable-next-line:no-console
console.log(`typeof Component is ${typeof Component}`);
export {
Component,
};
Run Code Online (Sandbox Code Playgroud)
然后,在我的应用程序中,我会使用import { Component } from '../library-wrapper.ts'
. 因为包装器使用动态导入表达式,Webpack 创建了一个单独的块,只有浏览器才真正需要它。\o/
.
但坏消息是:我的包装器实际上并不等待动态导入表达式。它调用loadLibrary()
函数但立即继续执行,记录
typeof 组件未定义
因此,当我尝试使用 时Component
,React 崩溃了:
元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件)但得到:未定义。
有什么建议是怎么回事?
loadLibrary
是一个异步函数,所以它返回一个promise而不是一个普通对象。因此,您必须执行await loadLibrary()
或loadLibrary().then(...)
获取库对象。
这样做的结果是您不能静态导出动态导入的内容,因为静态导入/导出是立即同步完成的,而动态导入是异步完成的。您只能导出函数loadLibrary
,并让模块的用户在需要库时调用该函数。
简而言之,一次异步,永远异步;你不能强制异步的东西在 JavaScript 中同步运行。
另外,loadLibrary
顺便说一句,您的功能可以简化很多,只需
const loadLibrary = () => import('library');
Run Code Online (Sandbox Code Playgroud)
因为 a).then((r) => r)
只是创建了一个承诺的相同副本,b) 在异步函数中返回之前你不必等待(它是自动完成的)和 c) 无论如何都返回一个承诺的函数不必被标记为async
(尽管如果您愿意,您仍然可以,例如为了可读性)。
归档时间: |
|
查看次数: |
11618 次 |
最近记录: |