在下面的代码中,我试图一次性发出多个(大约 10 个)HTTP 请求和 RSS 解析。
我在需要访问和解析结果的 URI 数组上使用标准的 forEach 结构。
代码:
var articles;
feedsToFetch.forEach(function (feedUri)
{
feed(feedUri, function(err, feedArticles)
{
if (err)
{
throw err;
}
else
{
articles = articles.concat(feedArticles);
}
});
});
// Code I want to run once all feedUris have been visited
我知道在一次调用函数时我应该使用回调。但是,在这个例子中,我能想到的使用回调的唯一方法是调用一个函数,该函数计算它被调用的次数,并且只有当它被调用的次数与 feedsToFetch.length 相同时才继续 这看起来很老套。
所以我的问题是,在 node.js 中处理这种情况的最佳方法是什么。
最好没有任何形式的阻塞! (我仍然想要那种超快的速度)。是 promise 还是其他?
谢谢, 丹尼
最佳答案
无黑客攻击的解决方案
Promises to be included in next JavaScript version
流行的 Promise 库为您提供了一个 .all() 方法用于这个确切的用例(等待一堆异步调用完成,然后做其他事情)。它非常适合您的场景
Bluebird 还有 .map(),它可以获取一个值数组并使用它来启动一个 Promise 链。
这是一个使用 Bluebird .map() 的例子:
var Promise = require('bluebird');
var request = Promise.promisifyAll(require('request'));
function processAllFeeds(feedsToFetch) {
return Promise.map(feedsToFetch, function(feed){
// I renamed your 'feed' fn to 'processFeed'
return processFeed(feed)
})
.then(function(articles){
// 'articles' is now an array w/ results of all 'processFeed' calls
// do something with all the results...
})
.catch(function(e){
// feed server was down, etc
})
}
function processFeed(feed) {
// use the promisified version of 'get'
return request.getAsync(feed.url)...
}
另请注意,您不需要在此处使用闭包来累积结果。
Bluebird API Docs写得也很好,有很多例子,所以更容易上手。
一旦我学习了 Promise 模式,它让生活变得更加轻松。我怎么推荐都不为过。
还有,这里是a great article关于使用 promises、async 模块和其他模块处理异步函数的不同方法
希望对您有所帮助!
关于javascript - Node.js:执行多个异步操作然后再做其他事情的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26268651/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试