请教各位老哥,有没有优雅的方式,在 express 中 如何先读取数据库,再启动后面的 中间件 ?

2021-09-08 01:36:05 +08:00
 qfdk

用 express 正在搞一个 oidc 服务器,认证服务器。 现在碰到点儿困难,官方文档的 clients 是写死在配置文件中的,只接受一个数组。

https://github.com/panva/node-oidc-provider 这个是使用的库

express 需要调用这个中间件。姑且叫做 oidc

我想要插数据库 拿到所有的 clients 信息,然后再来配置这个中间件中的 clients

因为查询数据库是异步的,也比较耗时,是 async 的程序,这样 app.js 中 都需要包裹在

(async ()=>{
const client = await queryDb();
const oidc = new OIDC({client});
 app.use(abc);
 app.use(oidc.callback());
 // module.exports = app; // 无法在 bin/www 启动
 app.listen()
})()

没有办法完成 export 到另外的 bin/www 文件启动。只能用 app.listen 来启动服务器。 我在想要是不改变文件夹结构的话,不知道要有啥法子 ?

queryDb().then(clients=>{
 const oidc = new OIDC({client});
 app.use(abc);
 app.use(oidc.callback());
});
module.exports = app;

这样感觉理论上应该没问题。 但是问题又来了 app 。use 是中间件 我想把 OIDC 的逻辑仍在另一个 config 文件夹里面 只返回 oidc 像这样

const clients= await queryDb(); // 这里需要放在 async 里面 这种方案理论上不行。因为要包裹在 async 里面,于是想到写个 init 
const oidc = new OIDC({client});
module.exports={oidc}


const {oidc} = require('./config');
app.use(abc);
app.use(oidc.callback());
module.exports = app;

想了三种方案,还是看看各位吴彦祖有没有好法子。先谢过了 看到个 类似的问题 https://stackoverflow.com/questions/49991740/can-i-export-the-result-of-an-asynchronous-function-with-module-export

751 次点击
所在节点    问与答
3 条回复
TomVista
2021-09-08 09:14:20 +08:00
自己搜一下 node 顶层 await,

我本来给你找好了文档,但是没发出去,而且站长封了我的 ip,神仙
Cbdy
2021-09-08 09:27:09 +08:00
1. top-level await
2. 导出工厂函数
qfdk
2021-09-08 15:12:30 +08:00
@TomVista #1 谢谢老哥!
@Cbdy 感谢思路 !

虽然问题还没有解决。

现在的问题,我要是 commonJS 的话 顶层 await 应该没法用吧,

谷歌了一下,说是 es2021 的新特性. 需要把 js 改成 mjs 。 不知道还有没有别的好法子。

我现在想的 一个是用事件。

把所有 app 用 event 包起来。如果 queryDb 事件完成,则执行里面的代码。

```javascript
myEmitter.on('ok', (data) => {
console.log('data');
app.get('/test', (req, res) => {res.send(data);}); // 可行
});
```

根据 @TomVista @Cbdy 顶层 await 的思路,需要改成 es6 的语法用 import 。
```javascript
// test.mjs ,因为需要支持语法 要用 mjs
const queryData = await import('./test-config.mjs');
class ABC {
constructor(name, data) {
this.name = name;
this.data = data;
}
}

const abc = new ABC('a', queryData);
console.log(abc); // 有数据
export default abc;
```

```javascript
// app.js
// express 自动生成代码
const app = express();
const abc = import('./config/test.mjs'); // 这里也要加入 await 么 ?如果加入 await 的话,这个 app.js 也需要改名了=> 上层 bin/www 内部引用也要改名
console.log(abc); // 这里还是 pending promise,没有数据
// view engine setup
app.set('views', path.join(__dirname, 'views')
...
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/800520

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX