NodeJs:对请求 url 使用异步 - Post 方法在执行所有 url 之前发送响应

NodeJs : Using async for request url - Post method sending response before execution of all urls

我有一个post方法,它的请求输入是一个newLink对象的列表(newLink有属性linkUrl和status) 我正在使用 async.map 遍历我的 URL 以检查链接是否处于活动状态。

newLinks 包含类似 {www.google.com,www.nourl.com,www.xyz.com} 的链接 我希望在处理所有请求并将相应状态设置为真或假之后,我想要这个使用 res.send(newLinks)

发送

但控制台给出以下结果:"www.google.com is up",然后调用 res.send(),然后执行 "www.nourl.com is up" 和 "www.xyz.com is up"

所以基本上在这里,在第一个 url 请求之后,我下面的代码在异步循环之外执行函数。我以为 async 只会在所有 url 都被验证后才允许下一段代码执行。

app.post('/myposturl', function(req , res){
var request = require('request');
let linkDetails= req.body.linkDetails;
var i = 0;
 async.map(linkDetails, function(newLink, callback) {
var Url = "url";
var url = newLink.linkUrl;
        var proxiedRequest = request.defaults({'proxy': Url});
        proxiedRequest(url , function (error, response, body) {

          if(error){
            console.log('Err: '+ error);
          }
        if (!error) {
        if(response.statusCode == 200 || response.statusCode == 201 || 
         response.statusCode == 202){
          console.log(url + ' is up!!');
          newLink.isActive = true;
        }

        if(response.statusCode == 301 || response.statusCode == 302){
          console.log(url + ' is redirecting us!!');
          return false;
        }
        }
        });
        callback();
        }  , function(err, linkDetails) {
       res.send(linkDetails);
        });
      //tried res.send here as well.
        });
    }

async.mapcallback 应该在 proxiedRequest 内部调用。您的代码现在正在做什么:在 proxiedRequest 完成之前立即调用 callback。另外 return false; 在异步函数中不起作用。你应该 return 这样的新状态 callback(null, newLink)。处理完所有请求后,newLinkDetails 将是所有 newLink.

的数组

Note, that since this function applies the iteratee to each item in parallel, there is no guarantee that the iteratee functions will complete in order.

如果您需要保留订单,请用户 mapSeries 代替。

请阅读 doc of async.map 了解更多信息。希望对你有帮助。

app.post('/myposturl', function(req , res){
  //other codes
  async.map(linkDetails, function(newLink, callback) {
    //other codes
    proxiedRequest(url , function (error, response, body) {
        if(error){
            console.log('Err: '+ error);
            callback(error);
            //^ ^  ^  ^  ^
            // Validation failed, return from here
        }
        else {
            //some validation & set newLink.isActive

            callback(null, newLink);
            // ^   ^    ^   ^    ^
            //return newLink status by invoking the callback
        }
    });
  }, function(err, newLinkDetails) {
      //err = if any Validation failed
      // now all the request are processed,newLinkDetails is array of all newLink's
      res.send(newLinkDetails);
  });
});

通常在使用async.js的时候,我遵循这两个原则:

  • 在异步函数期间始终至少调用一次 callback 并且最多调用一次。

  • 仅当异步函数完成或出现错误时才调用callback。如果发生后者,调用 callback 传递 error 并停止进一步执行异步函数,例如return callback(error)

我会修改你的代码如下:

var request = require('request');

app.post('/myposturl', function (req , res) {
    async.mapSeries(req.body.linkDetails || [], function(newLink, callback) {
        var Url = "url";
        var proxiedRequest = request.defaults({ 'proxy': Url });
        proxiedRequest(newLink.linkUrl, function (err, response, body) {
            if (err)
                return callback(err);
            // I'm assuming you don't want to stop checking the links for bad status codes
            if ([301, 302].indexOf(response.statusCode) > -1){
                return callback(null, url + ' is redirecting us!!');
            if ([200, 201, 202].indexOf(response.statusCode) == -1) {
                return callback(null, url + ' came back with ' + response.statusCode);

            console.log(url + ' is up!!');
            newLink.isActive = true;    
            callback(null, newLink);
        });
    }, function (err, linkDetails) {
        // when all links get checked, it will come down here
        // or if an error occurs during the iteration, it will come down here
        console.log(err, linkdetails);
        res.send(linkDetails);
    });
});

如果您只想取回活动链接,您可能还想查看 async.filterSeries()。这里 callback 需要在其第二个参数中传递一个布尔值。