我有一个简化的函数,看起来像这样:
function(query) {
myApi.exec('SomeCommand', function(response) {
return response;
});
}
我想让它调用myApi。Exec,返回回调lambda中给出的响应。然而,上面的代码不能工作,只是立即返回。
只是为了一个非常hack的尝试,我尝试了下面的工作,但至少你知道我想要实现什么:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
while (!r) {}
return r;
}
基本上,“node.js/事件驱动”的好方法是什么?我希望我的函数等待,直到回调被调用,然后返回传递给它的值。
注意:这个答案可能不应该在产品代码中使用。这是一个黑客,你应该知道它的含义。
有uvrun模块(这里更新了较新的Nodejs版本),您可以在其中执行libuv主事件循环(这是Nodejs主循环)的单个循环。
你的代码应该是这样的:
function(query) {
var r;
myApi.exec('SomeCommand', function(response) {
r = response;
});
var uvrun = require("uvrun");
while (!r)
uvrun.runOnce();
return r;
}
你也可以使用uvrun.runNoWait()。这可以避免一些阻塞问题,但占用100%的CPU。)
注意,这种方法在某种程度上否定了Nodejs的整个目的,即让所有内容都是异步和非阻塞的。此外,它可能会大大增加调用堆栈的深度,因此可能会导致堆栈溢出。如果你递归地运行这样的函数,你肯定会遇到麻烦。
请参阅其他关于如何重新设计代码以使其“正确”的答案。
这里的解决方案可能只在您进行测试时有用,特别是当您想要同步和串行代码时。
假设你有一个函数:
var fetchPage(page, callback) {
....
request(uri, function (error, response, body) {
....
if (something_good) {
callback(true, page+1);
} else {
callback(false);
}
.....
});
};
你可以像这样使用回调函数:
fetchPage(1, x = function(next, page) {
if (next) {
console.log("^^^ CALLBACK --> fetchPage: " + page);
fetchPage(page, x);
}
});
“好的node.js /事件驱动”的方法是不要等待。
与node等事件驱动系统一样,函数应该接受一个回调参数,该参数将在计算完成时被调用。调用者不应该等待正常意义上的值被“返回”,而是发送将处理结果值的例程:
function(query, callback) {
myApi.exec('SomeCommand', function(response) {
// other stuff here...
// bla bla..
callback(response); // this will "return" your value to the original caller
});
}
所以你不能这样使用它:
var returnValue = myFunction(query);
但就像这样:
myFunction(query, function(returnValue) {
// use the return value here instead of like a regular (non-evented) return value
});