如何使一个函数等待,直到使用node.js调用callback
我有一个简化的函数,看起来像这样:
function(query) { myApi.exec('SomeCommand', function(response) { return response; }); }
基本上我希望它调用myApi.exec
,并返回callbacklambda中给出的响应。 但是,上面的代码不起作用,只是立即返回。
只是为了一个非常冒险的尝试,我试了下面哪个都没用,但是至less你明白了我想要达到的目的:
function(query) { var r; myApi.exec('SomeCommand', function(response) { r = response; }); while (!r) {} return r; }
基本上,这是一个很好的“node.js /事件驱动”方式吗? 我希望我的函数等待callback被调用,然后返回传递给它的值。
这样做的“好node.js /事件驱动”的方式是不要等待 。
像使用事件驱动的系统(比如节点)一样,几乎所有的事情都是一样的,你的函数应该接受一个callback参数,这个参数在计算完成后会被调用。 调用者不应该等待正常意义上的“返回”值,而是发送处理结果值的例程:
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 });
检查这个: https : //github.com/luciotato/waitfor-ES6
你的代码用wait.for :(需要生成器,–harmony标志)
function* (query) { var r = yield wait.for( myApi.exec, 'SomeCommand'); return r; }
如果您不想使用回拨,则可以使用“Q”模块。
例如:
function getdb() { var deferred = Q.defer(); MongoClient.connect(databaseUrl, function(err, db) { if (err) { console.log("Problem connecting database"); deferred.reject(new Error(err)); } else { var collection = db.collection("url"); deferred.resolve(collection); } }); return deferred.promise; } getdb().then(function(collection) { // This function will be called afte getdb() will be executed. }).fail(function(err){ // If Error accrued. });
欲了解更多信息,请参阅: https : //github.com/kriskowal/q
注意:这个答案可能不应该用在生产代码中。 这是一个黑客,你应该知道的影响。
有一个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; }
(你可以select使用uvrun.runNoWait()
,这样可以避免一些阻塞问题,但是占用100%CPU。)
请注意,这种方法会使Nodejs的整个目的无效,即具有asynchronous和非阻塞的一切。 此外,它可以增加你的调用堆栈深度,所以你可能会结束堆栈溢出。 如果你recursion运行这个函数,你肯定会遇到麻烦。
请参阅关于如何重新devise代码的其他答案,以便“正确”。
这里的解决scheme可能只在testing和esp时才有用。 想要同步和串行代码。
如果你想要它非常简单,没有花哨的库,等待callback函数在节点执行,在执行其他代码之前,是这样的:
//initialize a global var to control the callback state var callbackCount = 0; //call the function that has a callback someObj.executeCallback(function () { callbackCount++; runOtherCode(); }); someObj2.executeCallback(function () { callbackCount++; runOtherCode(); }); //call function that has to wait continueExec(); function continueExec() { //here is the trick, wait until var callbackCount is set number of callback functions if (callbackCount < 2) { setTimeout(continueExec, 1000); return; } //Finally, do what you need doSomeThing(); }
这打破了非阻塞IO的目的 – 当你不需要阻塞的时候你会阻止它
你应该嵌套你的callback,而不是强迫node.js等待,或者在你需要r
的结果的callback中调用另一个callback。
有可能,如果你需要强制阻止,你正在考虑你的架构错误。
由于节点4.8.0,您可以使用称为发生器的ES6function。 您可以按照这篇文章获得更深入的概念。 但基本上你可以使用生成器和承诺来完成这项工作。 我正在使用蓝鸟 promisify和pipe理生成器。
你的代码应该像下面的例子一样好。
const Promise = require('bluebird'); function* getResponse(query) { const r = yield new Promise(resolve => myApi.exec('SomeCommand', resolve); return r; } Promise.coroutine(getResponse)() .then(response => console.log(response));
假设你有一个function:
var fetchPage(page, callback) { .... request(uri, function (error, response, body) { .... if (something_good) { callback(true, page+1); } else { callback(false); } ..... }); };
你可以使用像这样的callback:
fetchPage(1, x = function(next, page) { if (next) { console.log("^^^ CALLBACK --> fetchPage: " + page); fetchPage(page, x); } });
对我来说,它使用
JSON.parse(result)['key']
我期望的结果。 这可能不是“超级普通”,但最后“JSON.parse”pipe理等待asynchronous调用,而result['key']
没有。
exports.dbtest = function (req, res) { db.query('SELECT * FROM users', [], res, renderDbtest); }; function renderDbtest(result, res){ res.render('db', { result: result }); }
这是我如何做到的,你只需要通过“res”就可以,所以你可以稍后渲染
- 定义TypeScriptcallbacktypes
- 我如何dynamic调用PHP中的类方法?
- 当在JavaScript循环内使用callback时,有没有什么办法可以保存循环中更新的variables以便在callback中使用?
- 知道何时加载图像的Javascriptcallback
- 如何用纯英文解释callback? 它们与另一个函数调用一个函数有什么不同?
- 我怎样才能传递一个类的成员函数作为callback?
- 嵌套callback的Java模式?
- JavaScriptcallback范围
- 如何将一个额外的parameter passing给Javascript .filter()方法中的callback函数?