Javascript 在循环完成nodejs请求之前执行回调
我正在与API通信,以获取ID数组的信息。因此,数组中的每个id都需要一个对api的请求,如果响应符合逻辑,我想从响应中构建一个数据数组。但是,正在处理请求的my函数上的回调是在构建新数组之前执行的。在处理对api的大量调用时,我经常遇到这个问题。我如何修复这个特定的示例,以及将来解决这个问题的最佳方法是什么Javascript 在循环完成nodejs请求之前执行回调,javascript,arrays,node.js,request,lodash,Javascript,Arrays,Node.js,Request,Lodash,我正在与API通信,以获取ID数组的信息。因此,数组中的每个id都需要一个对api的请求,如果响应符合逻辑,我想从响应中构建一个数据数组。但是,正在处理请求的my函数上的回调是在构建新数组之前执行的。在处理对api的大量调用时,我经常遇到这个问题。我如何修复这个特定的示例,以及将来解决这个问题的最佳方法是什么 var request = require('request'); var _ = require('lodash'); var siteLayouts = [1550, 1552, 1
var request = require('request');
var _ = require('lodash');
var siteLayouts = [1550, 1552, 1554, 1556, 1558, 1560, 1562, 1564, 1566, 1568, 1570, 1572, 1574, 1730, 1734, 1736, 1738, 1740, 1896, 1898, 1900, 1902, 1904, 1906, 1908, 1910, 1914, 1922, 1924, 1926, 1928, 1930, 1932, 1934, 1936, 1938, 1940, 1942, 1944, 1946, 1948, 1950, 1952, 1954, 1956, 1958, 1960, 1962, 1964, 1966, 1968, 1970, 1972, 1974, 1976, 1978, 1980, 1984, 1986, 1988, 1990, 1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2020, 2022, 2030, 2032, 2034, 2036, 2038, 2040, 2042, 2044, 2046, 2048, 2052, 2054, 2056, 2060, 2062, 2064, 2066, 2068, 2070, 2072, 2122, 2124, 2148, 2154, 2156, 2270, 2272, 2274, 2374, 2418, 2688, 2692, 2968, 3756, 4094, 5122, 5524, 7326, 7494, 8704, 8886, 9226, 9232, 9234, 9236, 9238, 9830, 9836, 10052, 10054, 10056, 10999, 11083, 11085, 11429, 11513, 17279, 20397, 22285, 22287, 22289, 22291, 22293, 22295, 22807, 22809, 22811, 22813, 22815];
function getLayoutModules(siteLayouts, callback) {
var matchedModules = [];
for (var i = 0; i < siteLayouts.length; i++) {
request('http://PRIVATE-API-URL/layout/' + siteLayouts[i], function(err, res, body) {
if (!err && res.statusCode == 200) {
var layoutModules = JSON.parse(body);
var match = _.filter(layoutModules, {
'dtoLayoutModule': {
'ModuleName': 'Featured Content'
}
});
if (match.length > 0 && match[0].dtoLayoutModule) {
//console.log(match[0].dtoLayoutModule);
matchedModules.push(match[0].dtoLayoutModule);
console.log(matchedModules.length)
}
}
});
}
callback(matchedModules);
}
getLayoutModules(siteLayouts, function(matchedModules) {
console.log(matchedModules);
});
var request=require('request');
var=要求('lodash');
var站点布局=[1550, 1552, 1554, 1556, 1558, 1560, 1562, 1564, 1566, 1568, 1570, 1572, 1574, 1730, 1734, 1736, 1738, 1740, 1896, 1898, 1900, 1902, 1904, 1906, 1908, 1910, 1914, 1922, 1924, 1926, 1928, 1930, 1932, 1934, 1936, 1938, 1940, 1942, 1944, 1946, 1948, 1950, 1952, 1954, 1956, 1958, 1960, 1962, 1964, 1966, 1968, 1970, 1972, 1974, 1976, 1978, 1980, 1984, 1986, 1988, 1990, 1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2020, 2022, 2030, 2032, 2034, 2036, 2038, 2040, 2042, 2044, 2046, 2048, 2052, 2054, 2056, 2060, 2062, 2064, 2066, 2068, 2070, 2072, 2122, 2124, 2148, 2154, 2156, 2270, 2272, 2274, 2374, 2418, 2688, 2692, 2968, 3756, 4094, 5122, 5524, 7326, 7494, 8704, 8886, 9226, 9232, 9234, 9236, 9238, 9830, 9836, 10052, 10054, 10056, 10999, 11083, 11085, 11429, 11513, 17279, 20397, 22285, 22287, 22289, 22291, 22293, 22295, 22807, 22809, 22811, 22813, 22815];
函数getLayoutModules(站点布局、回调){
var matchedModules=[];
对于(var i=0;i0&&match[0].dtoLayoutModule){
//console.log(匹配[0].dtoLayoutModule);
matchedModules.push(匹配[0].dtoLayoutModule);
console.log(matchedModules.length)
}
}
});
}
回调(匹配的模块);
}
GetLayoutModule(站点布局、函数(匹配模块){
console.log(匹配的模块);
});
我已经验证了数据是通过console.log length添加到最终数组中的,但是我首先看到callback console.log,然后是长度。另外,这里还有一个使用u.filter筛选后的请求响应体示例
[{
RequestStatus: {
StatusCode: '200',
StatusTxt: 'Successful request.',
Result: 'Successful request.',
ValidationErrors: null
},
dtoLayoutModule: {
Id: 116013,
LayoutId: 10999,
LayoutName: 'layout name',
ModuleId: 7,
ModuleName: 'Featured Content',
DisplayName: 'name to display',
Position: 4,
Config: '<config><item name="layout" value="primary" /></config>',
MaxContentCount: 4,
CanInherit: false,
IsInheritable: false,
IsStaticModule: false
}
}]
[{
请求状态:{
状态代码:“200”,
StatusTxt:“请求成功”,
结果:“请求成功。”,
验证错误:null
},
DTOLayout模块:{
身份证号码:116013,
LayoutId:10999,
LayoutName:“布局名称”,
模块ID:7,
ModuleName:“特色内容”,
DisplayName:'要显示的名称',
职位:4,
配置:“”,
MaxContentCount:4,
卡尼赫特:错,
IsInheritable:错误,
IsStaticModule:false
}
}]
for
循环不能像您希望的那样与异步代码一起工作,因为它们仅用于同步代码。使用async.map
处理每个ID的异步请求。这将获取您的ID数组,对每个ID执行异步请求,并返回一个响应数组,然后您可以使用h常规数组.prototype.filter
在最终将匹配的模块
传递给回调之前。您遇到的问题是您在同步思考,并且在异步工作。您在循环中启动请求,并在循环后立即调用回调。但您无法保证所有calls将在您调用回调方法时被处理。事实上,相反的情况是可以保证的。您需要的是一种只有在处理完所有请求后才能调用回调的方法
我认为你应该考虑使用承诺。承诺是EcMASCRIPT6的一部分,并且今天通过各种库被密集地使用。最有名的一个(据我所知)是Q,但是还有其他的。< /P>
promise模式尝试(并且做得很好)消除所谓的“回调地狱”
以下是该模式的一个示例:
asyncCall()
.then(function(data1){
// do something...
return anotherAsyncCall();
})
.then(function(data2){
// do something...
return oneMoreAsyncCall();
})
.then(function(data3){
// the third and final async response
})
.fail(function(err) {
// handle any error resulting from any of the above calls
})
.done();
这个例子取自一篇名为Promises的文章,这是一种处理异步JavaScript的替代方法
在您的特定情况下,一种方法是收集承诺(每个承诺都是为每个请求创建的)进入一个承诺数组,然后使用Q.all方法。当所有承诺都得到解决时,该承诺就会得到解决。谢谢@PeterLyons。我一直试图避免使用异步库,因为我以前遇到过一些问题。但我想是时候学习它了!使用async.map和async.filter可以解决这个问题,谢谢@peterl!我已经看过了承诺以前是,但因为我主要使用nodejs承诺,这让我很困惑,这是一种不同于回调的编程方式。我需要花一些时间来学习它们,因为它们是ECMAScript 6的一部分。对教程或文档有什么建议吗?html5rocks(这是一个非常适合所有html内容的网站)有一篇关于承诺的好文章。它更像是一篇高水平的文章,但它是一个很好的起点: