如何导出从异步函数中获取其值的变量

Ejo*_*Ggg 9 javascript export es6-modules

如果我的问题听起来很愚蠢,我深表歉意,但我发现在许多情况下我需要在许多文件中使用全局变量,例如代表数据库和 redis 客户端的变量,但是这些变量本身需要等待从 promises 或 async 中获取它们的值初始化与数据库或 redis 服务器的通信的函数。

我想做这样的事情

init.js:

export default async () => {
   return await initializeWhatever()
}
Run Code Online (Sandbox Code Playgroud)

数据库.js:

import init from './init'
let db = null
init().then(val => db = val)
export default db
Run Code Online (Sandbox Code Playgroud)

api.js:

import db from './db'
const doApi = req => {
 db('users').select({username:req.param.username})
}
Run Code Online (Sandbox Code Playgroud)

但是db导入的变量api.js始终为空,为什么在init()完成时它没有更新为正确的值?如果我使用 db 的方法是错误的,那么导出异步计算的全局变量的正确方法是什么?

sri*_*ger 7

导出变量时,您导出的是变量中存储的内容,而不是变量本身。分配给变量只会更改变量,但不会影响导出的内容。

可以这样想:

let a = null;
let b = a;
a = 'something';
console.log(b);
// null
Run Code Online (Sandbox Code Playgroud)

请注意,在其中存储新内容如何a不会改变b.

要在问题中执行类似操作,您需要导出一个对象并更新该对象上的引用:

init.js

export default async () => {
    return await initializeWhatever()
}
Run Code Online (Sandbox Code Playgroud)

db-module.js

import init from './init'
const dbModule = { db: null };
init().then(val => dbModule.db = val)
export default dbModule
Run Code Online (Sandbox Code Playgroud)

api.js

import dbModule from './db-module'
const doApi = req => {
    dbModule.db.select({username:req.param.username})
}
Run Code Online (Sandbox Code Playgroud)

显然,您可能想要更改一些名称以使事情更简洁。我对你的项目了解不多,所以我不知道如何命名它们。

此外,您必须确保有某种方法来确保您的dbModule.db对象实际到位后进行任何使用。换句话说,你必须确保有没有办法doApiapi.js之前可调用initdb-module.js完成。

为此,您需要将承诺链从initavailable 设置为api.js

init.js

export default async () => {
    return await initializeWhatever()
}
Run Code Online (Sandbox Code Playgroud)

db-module.js

import init from './init'
const dbModule = { db: null };
dbModule.promise = init().then(val => dbModule.db = val)
export default dbModule
Run Code Online (Sandbox Code Playgroud)

api.js

import dbModule from './db-module'
const doApi = req => {
    dbModule.db.select({username:req.param.username})
}
dbModule.promise.then(() => {
    // Set up routes and start listening in this promise chain.
    // Ensure there is no way `doApi` can be called before this happens.
});
Run Code Online (Sandbox Code Playgroud)

为什么这样做?因为在 JS 中,变量不会存储对象的整个副本。它们只是存储引用。如果两个变量指向同一个对象,则无论您是通过一个变量还是另一个变量访问该对象,都将反映对该对象的更改。可以这样想:

let c = { prop: null };
let d = c;
c.prop = 'something';
console.log(d.prop);
// 'something'
Run Code Online (Sandbox Code Playgroud)

  • 我意识到我的评论可以更好地进行编辑。所以进行了编辑。:) (2认同)