我正在构建一个 NodeJS 应用程序(使用 Sails,但我想这无关紧要)。
在我的行动中,我有许多需要加载的对其他服务、数据源等的请求。但是,由于对回调的巨大依赖,我的代码在操作返回 HTML 后很长时间仍在执行。
我一定是错过了一些愚蠢的事情(或者没有完全了解整个异步的事情),但是在我准备好所有数据来渲染视图之前,我到底要如何阻止我的动作完成呢?!
干杯
我正在构建一个 NodeJS 应用程序(使用 Sails,但我想这无关紧要)。
在我的行动中,我有许多需要加载的对其他服务、数据源等的请求。但是,由于对回调的巨大依赖,我的代码在操作返回 HTML 后很长时间仍在执行。
我一定是错过了一些愚蠢的事情(或者没有完全了解整个异步的事情),但是在我准备好所有数据来渲染视图之前,我到底要如何阻止我的动作完成呢?!
干杯
我建议与异步库非常亲密
上面的链接的文档非常好,但它基本上归结为一堆非常方便的调用,例如:
async.parallel([
function(){ ... },
function(){ ... }
], callback);
async.series([
function(){ ... },
function(){ ... }
]);
Node本质上是异步的,你需要学会爱上它。
很难确切地说出问题出在哪里,但这里有一个猜测。假设您只有一个外部调用,您的代码应如下所示:
exports.myController = function(req, res) {
longExternalCallOne(someparams, function(result) {
// you must render your view inside the callback
res.render('someview', {data: result});
});
// do not render here as you don't have the result yet.
}
如果您有两个以上的外部调用,您的代码将如下所示:
exports.myController = function(req, res) {
longExternalCallOne(someparams, function(result1) {
longExternalCallTwo(someparams, function(result2) {
// you must render your view inside the most inner callback
data = {some combination of result1 and result2};
res.render('someview', {data: data });
});
// do not render here since you don't have result2 yet
});
// do not render here either as you don't have neither result1 nor result2 yet.
}
如您所见,一旦您有多个长时间运行的异步调用,事情就会开始变得棘手。上面的代码仅用于说明目的。如果您的第二个回调取决于第一个回调,那么您需要类似的东西,但如果 longExternalCallOne 和 longExternalTwo 彼此独立,您应该使用像async这样的库来帮助并行化请求https://github.com/caolan/async
你不能停止你的代码。如果一切都已完成,您所能做的就是检查所有回调。如果是,请继续使用您的代码。如果否,请等待下一次回调并再次检查。
我在这里猜测,因为没有代码示例,但你可能会遇到这样的事情:
// let's say you have a function, you pass it an argument and callback
function myFunction(arg, callback) {
// now you do something asynchronous with the argument
doSomethingAsyncWithArg(arg, function() {
// now you've got your arg formatted or whatever, render result
res.render('someView', {arg: arg});
// now do the callback
callback();
// but you also have stuff here!
doSomethingElse();
});
});
所以,在你渲染之后,你的代码会继续运行。如何预防?return
从那里。
return callback();
现在您的内部函数将在调用回调后停止处理。
你不应该停止你的代码,而是在你的其他资源回调中渲染你的视图,所以你在渲染之前等待你的资源被访问。这是 node.js 中的常见模式。
如果您必须等待多个回调被调用,您可以在每次调用一个回调时手动检查是否也调用了其他回调(例如使用简单的 bool),如果是,则调用您的渲染函数。或者您可以使用异步或其他很酷的库,这将使任务更容易。Promises(使用 bluebird 库)也可以是一个选项。