node.js循环使用承诺的GET

时间:2016-05-26 23:49:06

标签: javascript node.js asynchronous ftp promise

我对承诺不熟悉,我确信那里有答案/模式,但我找不到一个对我来说显而易见的正确答案。我使用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(失败和意外)等

3 个答案:

答案 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
});