如何初始化共享的javascript模块默认导出 [英] How to initialize a shared javascript module default export

查看:45
本文介绍了如何初始化共享的javascript模块默认导出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在多个模块之间共享一个api实例,并能够使用外部配置对其进行初始化.我的代码使用Webpack和Babel将那些不错的ES6模块转换为浏览器可以使用的模块.我正在努力实现这一目标:

I want to share an api instance across multiple modules and be able to initialize it with external configuration. My code uses Webpack and Babel to transform those nice ES6 modules into something usable by browsers. I'm trying to achieve this:

// api.js
let api = null;
export default api;
export function initApi(config) {
  // use config to configure the shared api instance (e.g. with api base url)
  api = ...
}


// ======================
// entry.js
import { initApi } from './api';
import App from './App';

// Initialize the single shared instance before anyone has the chance to use it
const apiConfig = ...
initApi(apiConfig);

// Create the app and run it


// ======================
// App.js
// RootComponent has an import dependency chain that eventually imports DeeplyNestedComponent.js
import RootComponent from './RootComponent';

// Actual App code not important


// ======================
// DeeplyNestedComponent.js
// PROBLEM! This "assignment" to the api var happens before initApi is run!
import api from '../../../../api';

api.getUser(123); // Fails because "api" stays null forever even after the initApi() call

问题"发生此问题是因为静态导入了ES6模块,并且提升了导入语句.换句话说,仅将 import App从 initApi(apiConfig)下的'./App'行移到 initApi 被称为.

The "problem" occurs because ES6 modules are imported statically and import statements are hoisted. In other words, simply moving the import App from './App' line below initApi(apiConfig) doesn't make the import happen after initApi is called.

解决此问题的一种方法是从 api.js (或如果我有多个具有相同模式的此类共享库,则在另一个 globals.js 文件中)导出对象),而不是像这样的单个变量:

One way to solve this is to export an object from api.js (or in another globals.js file if I have multiple such shared objects with the same pattern) instead of a single variable like this:

// api.js
const api = {
  api: null,
};
export default api;
export function initApi(config) {
  // use config to configure the shared api instance (e.g. with api base url)
  api.api = ... // <-- Notice the "api." notation
}


// ======================
// DeeplyNestedComponent.js
// api is now the object with an empty "api" property that will be created when initApi() is called
import api from '../../../../api';

api.api.getUser(123); // <-- Ugh :(

使用ES6模块时,有没有一种方法可以优雅地实现共享服务实例的初始化?

Is there a way to achieve initialization of a shared service instance elegantly when using ES6 modules?

就我而言, DeeplyNestedComponent.js 必须仍然以某种方式 import api实例.换句话说,不幸的是,没有任何上下文对象从 App 一直传递到 DeeplyNestedComponent.js ,可以访问api实例.

In my case, DeeplyNestedComponent.js must still import the api instance somehow. In other words, there is unfortunately no context object passed from App all the way down to DeeplyNestedComponent.js that could give access the api instance.

推荐答案

您的代码存在的问题是

let api = null;
export default api;

会在默认生成的隐式生成的绑定中导出 value null .但是,您也可以使用语法

does export the value null in the implicitly generated binding for the default export. However, you can also export arbitrary bindings under the name default by using the syntax

let api = null;
export { api as default };

这将按预期工作.但是在调用 initApi 之前,您仍然需要确保没有模块访问此导出.

This will work as expected. But you still need to make sure that no module accesses this export before you called initApi.

这篇关于如何初始化共享的javascript模块默认导出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆