在http数组上调用done.在Node.js中获取请求

Calling done on an array of http.get requests in Node.js

本文关键字:js 获取 请求 Node done http 数组 调用      更新时间:2023-09-26

我有一个url数组,我使用for循环调用http。get请求。由于这是一个异步进程,我想在所有请求返回后调用完成。

这是我当前的尝试:

grunt.registerTask('verify', function() {
    var done = this.async();
    var promises = [];
    var urlPrefix = 'http://example.com/';
    for(var i = 0; i < deployableFiles.length; i++) {
        (function(i) {
            var deferred = Q.defer();
            promises.push(deferred);
            var file = deployableFiles[i];
            var path =  file.filetype + '/' + getVersionedFileName(file.basename, file.filetype);
            http.get(urlPrefix + path, function(res) {
                deferred.resolve();
                if(res.statusCode === 200) {
                    grunt.log.oklns(path + ' was found on production server.');
                } else {
                    grunt.log.error('Error! ' + path + ' was not found on production server!');
                }
            }).on('error', function(e) {
                grunt.log.error("Got error: " + e.message);
                done();
            });
        })(i);
    }
    Q.all(promises)
    .done(function() {
        // Everything executed correctly
        return done();
    }, function(reason) {
        // There was an error somewhere
        return done(false);
    });
});

我敢肯定,这只是我没有把我的头围绕整个异步性质的节点正确,但有什么明显的其他人吗?

我已经搜索了关于使用http与Q库,它似乎可能需要使用Q.nfcall来让这个工作。我只是不明白我为什么要这么做。(我并不反对这样做,我更好奇的是什么)

谢谢!

如果这不是一个打字错误,promises.push(deferred)应该被推到承诺promises.push(deferred.promise)

function foo() {
  ...
  return defer.promise;
}
// => foo().then(function() ...);
Q.all([
  foo(),
  foo(),
  ...
]).done(function() ...);

Q.all期望一个承诺数组。

https://github.com/kriskowal/q组合

Q.nfcall只是周围的糖

处理使用Node.js回调模式的函数,其中回调的形式为function(err, result)

https://github.com/kriskowal/q adapting-node

您应该始终在尽可能低的级别执行约定。这使得对并发性的推理容易得多。

function getPing(url){
    return new Q.Promise(function(resolve,reject){
         http.get(url,function(res){
             // note this will _not_ wait for the whole request
             // but just the headers.
             if(res.statusCode === 200) resolve();
             else reject();
         });
    });
}

你可以这样做:

grunt.registerTask('verify', function() {
    var done = this.async();
    var urlPrefix = 'http://example.com/';
    var pings = deployableFiles.map(function(file){
        var path =  file.filetype + '/' + 
                        getVersionedFileName(file.basename, file.filetype);
        return getPing(urlPrefix + path);
    });
    Q.all(pings).then(done).catch(function(reason) {
        // There was an error somewhere
        // this will happen as soon as _one_ promise rejected
        return done(false);
    });
});

可以通过使用Bluebird等更好的promise库进一步缩短。

你也可以使用async:

var urlPrefix = 'http://example.com/';
async.each(deployableFiles, function(file, cb) {
  var path =  file.filetype
              + '/'
              + getVersionedFileName(file.basename, file.filetype);
  http.get(urlPrefix + path, function(res) {
    if (res.statusCode === 200)
      grunt.log.oklns(path + ' was found on production server.');
    else
      grunt.log.error('Error! ' + path + ' was not found on production server!');
    cb();
  }).on('error', function(e) {
    grunt.log.error("Got error: " + e.message);
    cb(e);
  });
}, function(err) {
  // all done
  if (err) throw err;
  // all successful
});