等待动态导入

时间:2018-04-07 10:37:50

标签: reactjs typescript async-await

我使用create-react-app使用React和Typescript创建了一个Web应用程序。它使用了相当重的第三方库。我想使用dynamic import expressions将其从主要包中排除。

所以,我没有做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,
};

然后,在我的应用中,我会使用import { Component } from '../library-wrapper.ts'。 因为包装器使用动态导入表达式,所以Webpack创建了一个单独的块,只有浏览器才会下载,然后才需要它。 \o/

但坏消息是:我的包装器实际上并没有等待动态导入表达式。它调用loadLibrary()函数但立即继续执行,记录

  

typeof Component未定义

所以当我尝试使用Component时,React崩溃了:

  

元素类型无效:期望一个字符串(用于内置组件)或一个类/函数(用于复合组件)但得到:undefined。

有什么建议吗?

1 个答案:

答案 0 :(得分:4)

loadLibrary是一个异步函数,因此它返回一个promise而不是一个常规对象。因此,您必须执行await loadLibrary()loadLibrary().then(...)才能获取库对象。

这样做的结果是您无法静态导出动态导入的内容,因为静态导入/导出是在异步完成动态导入时立即同步完成的。您只能导出函数loadLibrary,并让模块的用户在需要库时调用它。

简而言之,一旦异步,总是异步;你不能强迫异步在JavaScript中同步运行。

另外,除此之外,您的loadLibrary功能可能会被简化,只是

const loadLibrary = () => import('library');

因为a).then((r) => r)只是创建一个相同的承诺副本,b)你不必等待在返回异步函数之前(它自动完成)和c)a返回一个承诺的函数无论如何都不必标记为async(尽管如果你愿意,你仍然可以,例如,为了便于阅读)。