2013-02-08 94 views
1

我不确定这是否是正确的方式来做到这一点,但我期待在for循环中发出10个API请求,并且我希望每个API请求都被阻止。也就是说,要等到我收到响应而不需要回调,然后再次遍历foor循环。这里是福尔循环使API调用阻塞nodejs

for (var i=0; i< out.items.length; i++) { 
    var object = makediffbotAPIcall(out.items[i]); 
    console.log(object); 
} 

请求函数以下

function makediffbotAPIcall(item, array) { 
    var url_to_send_diffbot = "string of url here"; 

    request(url_to_send_diffbot, function (error, response, body) { 
     if (!error && response.statusCode == 200) { 
      var article_object = JSON.parse(body)  
      var object = {"Title": article_object.title, "Url":article_object.url}; 
     } 

    }); 

    return object; 
} 

的这段代码的问题是,对象时间福尔循环来利用它不会返回。我试图在makediffbotAPIcall函数的末尾放置一个setTimeout,但这也不起作用。任何建议,非常感谢。谢谢!

+0

可能重复的[我如何使这个调用请求在nodejs同步吗?](http://stackoverflow.com/questions/9884418/how-can-i-make-this-call-to-request-in -nodejs-synchronous) – JohnnyHK 2013-02-08 21:46:16

+0

你正在寻找的魔法词是异步信号量http://en.wikipedia.org/wiki/Asynchronous_semaphore – 2013-02-08 22:13:24

回答

4

有一个很好的node.js库“async”用于管理异步环境中的控制流。对于这个特定的issuse https://github.com/caolan/async#forEach系列版本并且在makediffbotAPIcall稍加修改,使事情的工作完全一样,你正在寻找所以这里的解决方案

async.forEachSeries(out.items,function(item,callback){ 
makediffbotAPIcall(item,out.items,function(object){ 
//here you will get either object or null 
callback(); 
}),function(err){ 
// this will be called when all array items will get processed 
}) 

function makediffbotAPIcall(item, array, callback) { 

var url_to_send_diffbot = "string of url here" 


request(url_to_send_diffbot, function (error, response, body) { 
    if (!error && response.statusCode == 200) { 
     var article_object = JSON.parse(body)  
     return callback({"Title": article_object.title, "Url":article_object.url}) 

    } 
    else 
     return callback(null); 
}) 
} 

我不知道有关的第二个参数makediffbotAPIcall我假设你想要传递完整的数组,所以我只是传递整个数组,如果不是这样,你可以根据需要修改它。

让我知道如果您有任何问题。

+0

这是一个很好的答案。非常感谢你的帮助。它现在有效。 – 2013-02-11 22:22:39

0

我发现在JS异步处理问题,以移动所有匿名函数,暂时当它往往是有用的,当他们正在通过,当他们正在调用明确显示。

function makediffbotAPIcall(item, array) { 

    var url_to_send_diffbot = "string of url here" 

    var receiveResponse = function (error, response, body) { 
     if (!error && response.statusCode == 200) { 
      var article_object = JSON.parse(body); 
      var object = {"Title": article_object.title, "Url":article_object.url}; 
     } 
    } 

    request(url_to_send_diffbot, receiveResponse); 
    return object; 
} 

所以这里有一些问题。第一,即使你的请求是同步的(对于可怜的旧单线程JavaScript,这将是一件可怕的事情),但这是行不通的,因为你在receiveResponse内使用var object,所以变量在该函数之外将不可用!

对于这个特殊的问题,最简单的解决方案是在receiveResponse内部调用console.log(object)。假设你已经简化了一些更复杂的代码,可用的模式有很多种。重要的是每个请求在前一个请求之后顺序发生,还是可以并行运行并单独记录(可能不按顺序)?基本上,你需要添加一个回调参数到makediffbotAPIcall,并调用objectresponseReceived之内的函数,或者返回一个Promise对象,除非你已经使用了一个提供它们的框架/库,否则这可能是过度杀毒,或者你真的需要对并行和/或顺序操作提供大量支持。

我重读你的问题,它看起来像你想阻止行为,这里是一个纯JS的解决方案(没有LIB需要= P)使用递归:

var i=0; 
var callNext = function(object){ 
    if(i<out.items.length) { 
     makediffbotAPIcall(out.items[i], callNext); 
    } 
    console.log(object); 
    i++; 
} 

callNect("nothing to log for first obj"); 

function makediffbotAPIcall(item, array, callback) { 

    var url_to_send_diffbot = "string of url here" 

    var receiveResponse = function (error, response, body) { 
     if (!error && response.statusCode == 200) { 
      var article_object = JSON.parse(body); 
      var object = {"Title": article_object.title, "Url":article_object.url}; 
      callback(object); 
     } 
    } 

    request(url_to_send_diffbot, receiveResponse); 
} 

这可能与一些整理做(递归的基本情况的处理很笨拙)但你并不总是需要一个库;)

0

你需要来自async.js库的forSeries(arr,iterator,callback)。

它所做的是它以非重叠的顺序方式遍历arr。适合重复性任务按顺序执行。所有迭代完成后调用回调。最好的部分是干净利落,没有回调的麻烦。

你应该尝试async.js的其他功能。这是一个伟大的图书馆,非常方便。

1

Async.js是一个良好的开端,还有其他像这样的 - https://github.com/joyent/node/wiki/modules#wiki-async-flow

但是请注意,那是阻挡“的代码是不是在节点/ JS是个好主意。它是一种单线程事件驱动的语言。你不想阻止代码,因为那么你的服务器就会停止响应请求。 由于上述原因,大多数asnyc模式都会要求您提供一个回调函数,有时称为“下一个”,您需要在每个函数结束时调用该函数,以便调用下一个函数。