1

我不确定这是否是正确的方法,但我希望在一个 for 循环中发出 10 个 API 请求,并且我希望每个 API 请求都被阻塞。也就是说,等到我收到响应而不去回调,然后再次遍历 foo 循环。这是for循环

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;
}

这段代码的问题是对象没有及时返回以便 for 循环使用它。我尝试在 makediffbotAPIcall 函数的末尾放置一个 setTimeout,但这也不起作用。任何建议都非常感谢。谢谢!

4

4 回答 4

4

有一个非常好的 node.js 库“async”用于管理异步环境中的控制流。对于这个特定的问题,请使用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 的第二个参数我假设你想传递完整的数组,所以我只是传递整个数组,如果不是这种情况你可以根据需要修改它。

如果您有任何问题,请告诉我。

于 2013-02-09T09:19:01.247 回答
1

Async.js 是一个很好的起点,还有其他类似的 - https://github.com/joyent/node/wiki/modules#wiki-async-flow

但是请注意,“阻塞”代码在 node/js 中并不是一个好主意。它是一种单线程事件驱动语言。您不想阻止代码,因为例如,您的服务器将停止对请求做出反应。由于上述原因,大多数 asnyc 模式会要求您提供一个回调函数,有时称为“下一个”,您需要在每个函数的末尾调用它,因此将调用行中的下一个函数。

于 2013-04-10T06:35:23.420 回答
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,这将是一件可怕的事情),这也不起作用,因为您使用var objectinside receiveResponse,因此该变量在该函数之外将不可用!

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

我重新阅读了你的问题,看起来你想要阻止行为,这是一个使用递归的纯 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);
}

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

于 2013-02-08T22:07:03.087 回答
0

您需要 async.js 库中的 forEachSeries(arr, iterator, callback) 。

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

您应该尝试 async.js 中的其他功能。这是一个很棒的图书馆,非常方便。

于 2013-02-08T22:07:18.173 回答