我对承诺不熟悉,我确信那里有答案/模式,但我找不到一个对我来说显而易见的正确答案。我使用node.js v4.2.4和https://www.promisejs.org/
我认为这应该很容易......我需要按特定顺序执行多个异步块,其中一个中间块将循环遍历HTTP GET数组。
// New Promise = asyncblock1 - FTP List,解析返回的列表数组 //.then(asynchblock2(list)) - 循环遍历列表数组和HTTP GET所需的文件 //.then(asynchblock3(list)) - 更新本地日志
我尝试创建一个新的Promise,解析它,将列表传递给.then,执行GET循环,然后进行文件更新。我尝试在asynchblock2中使用嵌套的promise.all,但由于这些事件的时间安排,它实际上以相反的顺序,3,2和1进行。谢谢你的帮助。
编辑:好的,这是我正在使用的模式,我现在只需要在中间的GET循环。var p = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('2 sec');
resolve(1);
},
2000);
}).then(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('1.5 sec');
// instead of this section, here I'd like to do something like:
// for(var i = 0; i < dynamicarray.length; i++){
// globalvar[i] = ftpclient.getfile(dynamicarray[i])
// }
// after this loop is done, resolve
resolve(1);
},
1500);
});
}).then(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('1 sec');
resolve(1);
},
1000);
});
});
编辑这是几乎正常工作的代码!
var pORecAlert = (function(){
var pa;
var newans = [];
var anstodownload = [];
var anfound = false;//anfound in log file
var nexttab;
var lastchar;
var po;
var fnar = [];
var antext = '';
//-->> This section works fine; it's just creating a JSON object from a local file
try{
console.log('trying');
porfile = fs.readFileSync('an_record_files.json', 'utf8');
if(porfile == null || porfile == ''){
console.log('No data in log file - uploaded_files_data.json being initialized!');
plogObj = [];
}
else{
plogObj = JSON.parse(porfile);
}
}
catch(jpfp){
console.log('Error parsing log file for PO Receiving Alert: ' + jpfp);
return endPORecAlertProgram();
};
if((typeof plogObj) === 'object'){
console.log('an_record_files.json log file found and parsed for PO Receiving Alert!');
}
else{
return mkError(ferror, 'pORecAlert');
};
//finish creating JSON Object
pa = new Client();
pa.connect(ftpoptions);
console.log('FTP Connection for FTP Check Acknowledgement begun...');
pa.on('greeting', function(msg){
console.log('FTP Received Greeting from Server for ftpCheckAcknowledgement: ' + msg);
});
pa.on('ready', function(){
console.log('on ready');
//START PROMISE LIST
var listpromise = new Promise((reslp, rejlp) => {
pa.list('/public_html/test/out', false, (cerr, clist) => {
if(cerr){
return mkError(ferror, 'pORecAlert');
}
else{
console.log('Resolving clist');
reslp(clist);
}
});
});
listpromise.then((reclist) => {
ftpplist:
for(var pcl = 0; pcl < reclist.length; pcl++){
console.log('reclist iteration: ' + pcl);
console.log('checking name: ', reclist[pcl].name);
if(reclist[pcl].name.substring(0, 2) !== 'AN'){
console.log('Not AN - skipping');
continue ftpplist;
}
else{//found an AN
for(var plc = 0; plc < plogObj.length; plc++){
if(reclist[pcl].name === plogObj[plc].anname){
//console.log('Found reclist[pcl].name in local log');
anfound = true;
};
};
if(anfound === false){
console.log('Found AN file to download: ', reclist[pcl].name);
anstodownload.push(reclist[pcl].name);
};
};
};
console.log('anstodownload array:');
console.dir(anstodownload);
return anstodownload;
}).then((fnar) => {
//for simplicity/transparency, here is the array being overwritten
fnar = new Array('AN_17650_37411.699.txt', 'AN_17650_37411.700', 'AN_17650_37411.701', 'AN_17650_37411.702.txt', 'AN_17650_37411.801', 'AN_17650_37411.802.txt');
return Promise.all(fnar.map((gfname) => {
var nsalertnames = [];
console.log('Getting: ', gfname);
debugger;
pa.get(('/public_html/test/out/' + gfname), function(err, anstream){//THE PROBLEM IS THAT THIS GET GETS TRIGGERED AN EXTRA TIME FOR EVERY OTHER FILE!!!
antext = '';
console.log('Get begun for: ', gfname);
debugger;
if(err){
ferror.nsrest_trace = 'Error - could not download new AN file!';
ferror.details = err;
console.log('Error - could not download new AN file!');
console.log('************************* Exiting *************************')
logError(ferror, gfname);
}
else{
// anstream.on('data', (anchunk) => {
// console.log('Receiving data for: ', gfname);
// antext += anchunk;
// });
// anstream.on('end', () => {
// console.log('GET end for: ', gfname);
// //console.log('path to update - gfname ', gfname, '|| end text.');
// fs.appendFileSync(path.resolve('test/from', gfname), antext);
// console.log('Appended file');
// return antext;
// });//end end
};
});//get end
}));//end Promise.all and map
}).then((res99) => {
// pa.end();
// return Promise(() => {
console.log('end all. res99: ', res99);
// //res4(1);
// return 1;
// });
});
});
})();
- &GT;&GT;这里发生了什么: 所以我添加了几乎可以工作的代码。发生的事情是,对于每个其他文件,都会收到一个额外的Get请求(我不知道它是如何被触发的),这会导致&#34;无法进行数据连接&#34;
因此,对于这个6的数组的迭代,最终会有9个Get请求。元素1被请求(工作和预期),然后2(工作和预期),然后2再次(失败和意外/不知道它被触发的原因)。然后3(工作和预期),然后4(工作和预期),然后再4(失败和意外)等
答案 0 :(得分:0)
您需要的是Promise.all()
,您应用的示例代码:
...
}).then(() => {
return Promise.all(arry.map(item => ftpclient.getFile(item)))
}).then((resultArray) => {
...
答案 1 :(得分:0)
非常感谢你的帮助(以及没有有用指示的否定投票!)
我实际上联系了一个优秀的nodejs程序员,他说我正在使用的ftp模块中似乎有一个错误,即使在尝试使用blackbird .map时,快速连续的请求也开始了错误。我最终使用了promise-ftp,blackbird和promiseTaksQueue - 踢球者是我需要 interval 。没有它,ftp最终会导致ftp模块出现奇怪的不合逻辑错误。
答案 2 :(得分:-1)
您需要异步库。在需要在循环中使用异步操作的情况下使用async.eachSeries,然后在所有这些操作完成时执行函数。根据您想要的流程有很多变化,但是这个库可以完成所有这些。
https://github.com/caolan/async
async.each(theArrayToLoop, function(item, callback) {
// Perform async operation on item here.
doSomethingAsync(item).then(function(){
callback();
})
}, function(err){
//All your async calls are finished continue along here
});