如何使用promises等待异步API调用(How to use promises to wait for async API calls)
我正在创建一个API,当GET对新闻API进行一系列调用时,新闻文章标题被提取到一个巨大的字符串中,并且该字符串被处理成一个对象,以便传递给前端的wordcloud。 到目前为止,我已经能够使用下划线的
_.after
和request-promise使我的应用程序等到所有API调用完成后再调用processWordBank()
,它接受巨型字符串并将其清理成对象。 但是,一旦processWordBank()
,我就不明白程序的流程在哪里。 理想情况下,processWordBank()
将obj返回到路由器中的cloudObj,以便obj可以传递给res.json()
并作为响应吐出。 我相信我对_.after
使用让我陷入了一种奇怪的境地,但这是我能够在进行下一个所需动作之前完成异步调用的唯一方法。 有什么建议么?(我试图省略所有不必要的代码,但如果这还不够,请告诉我)
// includes... var sourceString = "" // router export default ({ config }) => { let news = Router() news.get('/', function(req, res){ var cloudObj = getSources() res.json({ cloudObj }) }) return news } // create list of words (sourceString) by pulling news data from various sources function getSources() { return getNewsApi() } // NEWS API // GET top 10 news article titles from News API (news sources are determined by the values of newsApiSource array) function getNewsApi() { var finished = _.after(newsApiSource.length, processWordBank) for(var i = 0; i < newsApiSource.length; i++) { let options = { uri: 'https://newsapi.org/v1/articles?source=' + newsApiSource[i] + '&sortBy=' + rank + '&apiKey=' + apiKey, json: true } rp(options) .then(function (res) { let articles = res.articles // grab article objects from the response let articleTitles = " " + _.pluck(articles, 'title') // extract title of each news article sourceString += " " + articleTitles // add all titles to the word bank finished() // this async task has finished }) .catch(function (err) { console.log(err) }) } } // analyse word bank for patterns/trends function processWordBank(){ var sourceArray = refineSource(sourceString) sourceArray = combineCommon(sourceArray) sourceArray = getWordFreq(sourceArray) var obj = sortToObject(sourceArray[0], sourceArray[1]) console.log(obj) return obj }
I am creating an API that when GET, a series of calls to the News API are made, news article titles are extracted into a giant string, and that string is processed into an object to be delivered to a wordcloud on the front-end. So far, I've been able to use underscore's
_.after
and request-promise to make my app wait till all API calls have completed before callingprocessWordBank()
which takes the giant string and cleans it up into an object. However, onceprocessWordBank()
is called, I don't understand where the flow of the program is. Ideally,processWordBank()
returns obj to cloudObj in the router, so that the obj can be passed tores.json()
and spit out as the response. I believe my use of_.after
has put me in a weird situation, but it's the only way I've been able to get async calls to finish before proceeding to next desired action. Any suggestions?(I've tried to leave out all unnecessary code but let me know if this is insufficient)
// includes... var sourceString = "" // router export default ({ config }) => { let news = Router() news.get('/', function(req, res){ var cloudObj = getSources() res.json({ cloudObj }) }) return news } // create list of words (sourceString) by pulling news data from various sources function getSources() { return getNewsApi() } // NEWS API // GET top 10 news article titles from News API (news sources are determined by the values of newsApiSource array) function getNewsApi() { var finished = _.after(newsApiSource.length, processWordBank) for(var i = 0; i < newsApiSource.length; i++) { let options = { uri: 'https://newsapi.org/v1/articles?source=' + newsApiSource[i] + '&sortBy=' + rank + '&apiKey=' + apiKey, json: true } rp(options) .then(function (res) { let articles = res.articles // grab article objects from the response let articleTitles = " " + _.pluck(articles, 'title') // extract title of each news article sourceString += " " + articleTitles // add all titles to the word bank finished() // this async task has finished }) .catch(function (err) { console.log(err) }) } } // analyse word bank for patterns/trends function processWordBank(){ var sourceArray = refineSource(sourceString) sourceArray = combineCommon(sourceArray) sourceArray = getWordFreq(sourceArray) var obj = sortToObject(sourceArray[0], sourceArray[1]) console.log(obj) return obj }
原文:https://stackoverflow.com/questions/42340237
最满意答案
我会
reduce
您感兴趣的术语:hash = {a: 1, b: 2, d: 4} [:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h }
I would use a
reduce
of the terms you are interested in:hash = {a: 1, b: 2, d: 4} [:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h }
相关问答
更多-
请注意,使用gets ,输入可以包含换行符和回车符。 你需要使用gets.chomp来过滤这些。 这可能是您程序中问题的原因。 比较以下两个: > puts gets.size "Hello!" # 7 > puts gets.chomp.size "Hello!" # 6 请注意,您仍然需要扩展程序以考虑用户输入的键不在您的哈希中。 Note that when you use gets, the input can contain newline and carriage return charac ...
-
Ruby使用hash和eql? 检查哈希键的相等性。 看起来OpenStudio::OptionalString可能无法正确实现这些。 如果是这种情况,您的最佳解决方案是使用另一个密钥。 Ruby对散列键做出以下假设 - 如果两个对象被认为是相同的键,则它们必须返回相同的hash值,但是具有相同的散列值并不意味着它们是相同的键。 方法eql? 在内部用于解决这些情况。 你还可以修复hash和eql? OpenStudio::OptionalString类上的方法,但也许该库在内部依赖于“破坏”的行为。 这就 ...
-
正如我在评论中所描述的那样,只有弹出一个键,如果有的话: def build_hash(arr) h = {} keys = [] while arr.size > 0 current_token = arr.shift if alpha?(current_token) if keys.empty? # that means a new key is to be expected keys << current_token else ...
-
在注入方法中初始化一个散列以防止值为零(Initialize a hash in the inject method to prevent a value being nil)[2022-07-12]
解决方案 你可以使用each_with_object : array = [{'a': 1, 'b': 2, 'c': 3}, {'a': 4, 'b': 5, 'c': 6}, {'a': 7, 'b': 8, 'c': 9}] empty_hash = Hash.new{ |h, k| h[k] = [] } hash = array.each_with_object(empty_hash) do |small_hash, hash| small_hash.each do |k, v| h ... -
当密钥不存在时,从Hash#[]返回self(而不是nil)(Return self (rather than nil) from Hash#[] when key doesn't exist)[2023-06-22]
如果您只想返回新值但不想添加它们: h = Hash.new { |_hash, key| key } 要最初填充此哈希,您可以执行以下操作: h.merge( {1 => "one", 2 => "two"} ) 如果已经创建了哈希*: h.default_proc = proc do |_hash,key| key end #h[3] #=> 3 * 仅限于红宝石1.9及以上版本 If you only want to return new values but not ad ... -
这是从查询中获取对象的正确方法。 如果你仍然没有,那么你应该检查你的“BarLibrary”类表有的数据(并且可能在这里发布样本内容,以便了解它的结构)当前登录打印出PFObjects而不管它们的属性如何。 import Foundation import Parse struct getBarJSON { init(){ let query = PFQuery(className: "BarLibrary") query.findObjectsInBackgroundWithBl ...
-
如果给定键不存在,则Hash#slice like返回nil的方法(Hash#slice like method that returns nil if given key are not present)[2023-08-19]
我会reduce您感兴趣的术语: hash = {a: 1, b: 2, d: 4} [:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h } I would use a reduce of the terms you are interested in: hash = {a: 1, b: 2, d: 4} [:a, :c, :d].reduce({}) {|h, k| h[k] = hash[k]; h } -
NSURLResponse返回nil?(NSURLResponse returns nil?)[2023-08-12]
你有两个问题: 您在该URL的开头有一个额外的空间。 删除多余的空间。 您正在对已经转义百分比的URL调用stringByAddingPercentEscapesUsingEncoding 。 删除对stringByAddingPercentEscapesUsingEncoding此调用。 You have two issues: You have an extra space at the start of that URL. Remove that extra space. You are callin ... -
为此,我认为Enumerable#find可能有效: find(ifnone = nil) { |obj| block } → obj or nil find(ifnone = nil) → an_enumerator 将枚举中的每个条目传递给阻止。 返回第一个块不为false的块。 如果没有对象匹配,则调用ifnone并在指定时返回结果,否则返回nil 。 如果没有给出块,则返回一个枚举器。 在你的情况下,它会返回第一个块不是nil : p %i[c b a].find { |key| !{ a: 1, ...
-
如果OpenStruct中不存在密钥,我该如何返回nil?(How can I return nil if a key does not exist in OpenStruct?)[2021-09-11]
OpenStruct不是递归的。 在这种情况下, TXT.ftp返回Hash,而不是OpenStruct,因此#lastname 。 如果需要,有一个名为recursive-open-struct的库。 像这样用它: require 'recursive-open-struct' TXT = RecursiveOpenStruct.new(TXT_HASH) pp TXT.ftp.lastname #=> nil OpenStruct is not recursive. In this case TXT ...