【发布时间】:2018-07-09 19:22:34
【问题描述】:
TL;DR:有没有办法等待具有异步功能的模块导入完成,然后在调用模块中继续执行以保持模块功能的包含?
我正在开发一个个人节点项目,随着代码库的不断增长,我一直在以模块化/OOP 方式构建该项目。一项要求是启用跨模块/对象的日志记录,其中可以在不同时间记录不同的日志文件。我认为通过创建一个带有 init 函数的 Logger.js 文件,我已经以一种非常干净的方式解决了这个问题,只需在我需要的任何模块中导入 Logger.js 文件,我就可以随时使用该文件。以下是用于说明这一点的精简代码:
Logger.js
module.exports.init = function(location) {
var logFileBaseName = basePath + fullDatePathName;
var studentLogFile = fs.createWriteStream(logFileBaseName + '-student.log', {flags : 'a'});
var teacherLogFile = fs.createWriteStream(logFileBaseName + '-teacher.log', {flags : 'a'});
this.studentLog = function () {
arguments[0] = '[' + Utils.getFullDate() + '] ' + arguments[0].toString();
studentLogFile.write(util.format.apply(null, arguments) + '\n');
}
this.teacherBookLog = function () {
arguments[0] = '[' + Utils.getFullDate() + '] ' + arguments[0].toString();
teacherLogFile.write(util.format.apply(null, arguments) + '\n');
}
}
这看起来很棒,因为在我的主要入口点我可以简单地做:
Main.js
const Logger = require('./utils/Logger');
Logger.init(path);
Logger.studentLog('test from Main');
// all my other code and more logging here
在我的其他几十个文件中,我可以做的更少:
另一个文件.js
const Logger = require('./utils/Logger');
Logger.studentLog('test from AnotherFile')
然后要求不仅要记录到“学生日志”的文件,还要记录到 Discord(聊天客户端)。看起来很简单,我有这个 Logger 文件,我可以初始化 Discord 并在“学生日志”旁边登录到 Discord,如下所示:
Logger.js
module.exports.init = function(location) {
// code we've already seen above
var client = new Discord.Client();
client.login('my_login_string');
channels = client.channels;
this.studentLog = function () {
arguments[0] = '[' + Utils.getFullDate() + '] ' + arguments[0].toString();
var message = util.format.apply(null, arguments) + '\n';
studentLogFile.write(message);
channels.get('the_channel_to_log_to').send(message)
}
// more code we've already seen above
}
问题是如果你再次重新运行 Main.js,studentLog 会失败,因为 .login() 函数是异步的,它返回一个 Promise。登录尚未完成,当我们尝试调用 Logger.studentLog('test from Main'); 时,频道将是一个空集合
我已经尝试在 Logger.js 中使用 Promise,但在 Logger.js 中返回 Promise 之前,Main.js 的执行当然会继续。如果 Main.js 可以简单地等到 Discord 登录完成,我会喜欢它。
我的问题是,在保持我一直使用的模式的同时,最好的方法是什么?我知道我可以将整个 main 函数包装在等待 Discord 登录完成的 promise.then() 中,但这对我来说似乎有点荒谬。我试图将功能包含在模块中,并且不希望这种 Logger 代码/逻辑溢出到我的其他模块中。我想将它保留为一个简单的 Logger 导入,就像我一直在做的那样。
任何建议都会很棒!
【问题讨论】:
-
您不想在
.then中将客户端登录包装在logger.js 中吗?即client.login(token).then(success=>{//everything else});,因为这似乎是最简单的。 -
拥抱异步模式,放弃同步模式。以后你会过上幸福的生活。
-
@Wright 我确实尝试在 Logger 中用 .then() 包装它。问题是在 Logger 到达 .then() 之前 main 仍在继续,这意味着它会在完全初始化之前尝试使用 Discord 客户端。
-
@trincot 目标肯定是拥抱异步模式,但是如何实现呢?您是否建议放弃将所有 Logger 逻辑包含在 Logger.js 中,并使用等待 Discord 的 login() 函数返回的承诺包装我的所有 Main.js 代码?
-
您肯定需要将所有依赖于异步结果的代码放入回调中(用于承诺的
then回调)或async/await构造:两者都涉及函数包装器。当然,您可以从此类回调中调用其他函数。
标签: node.js asynchronous promise synchronous discord