具有setTimeout的节点js顺序请求无法使输出数组进一步进入进程

时间:2017-12-24 04:45:56

标签: javascript node.js async-await

使用synchronous request with

的顺序请求

使用Rest Api get方法在1秒内调用settimeout的顺序请求。 每次请求数据后按摩并放入数组。 现在我想在所有请求完成后得到这个数组。

       async function sequentialMF(mfIds) {
        var mfData = [];
        try {
            var timeout = 0;
            return await Promise.all(mfIds.map(mfId => {
                console.log(mfId)
                var options = {
                    //https://www.quandl.com/api/v3/datasets/AMFI/103504.json?api_key=WfUR65SA5p1PzpBysgK4
                    method: 'GET',
                    url: 'https://www.quandl.com/api/v3/datasets/AMFI/' + mfId + '.json',
                    qs: { api_key: 'WfUR65SA5p1PzpBysgK4' },
                };
                setTimeout(function () {
                    request(options, function (error, response, body) {
                        var obj = JSON.parse(body);
                        var mfobj = {
                            "code": obj.dataset.dataset_code,
                            "name": obj.dataset.name,
                            "date": obj.dataset.end_date,
                            "nav": obj.dataset.data[0][1]
                        }
                        mfData.push(mfobj);
                        console.log(obj.dataset.dataset_code + '  ' + obj.dataset.data[0][1]);
                        console.log('lngth ' + mfData.length + '  ' + mfIds.length)
                    })
                }, timeout);
                timeout += 1000;
                new Promise(function (resolve, reject) {
                    if (mfData.length === mfIds.length) {
                        console.log('testing')
                        resolve(mfData);
                    } else reject('errrrrrrrrrrrrror')
                })
            }))
        } catch (err) {
            console.log(err)
        }
    }

1 个答案:

答案 0 :(得分:0)

使用mapPromise.all将所有请求序列化为一个结果,而不是reduce.then。您还可以捕获失败请求的任何错误,以便最终获得结果。

//create Fail type instead of rejecting promise
function Fail(details){this.details=details;};
const isFail = item => (item&&item.constructor)===Fail
const sequentialMF = mfIds =>
  mfIds.reduce(//reduce ids to one promise
    (acc,mfId) =>
      acc.then(//acc is the one promise resolving to array of result or Fail items
        results => {
          var options = {
            //https://www.quandl.com/api/v3/datasets/AMFI/103504.json?api_key=WfUR65SA5p1PzpBysgK4
            method: 'GET',
            url: 'https://www.quandl.com/api/v3/datasets/AMFI/' + mfId + '.json',
            qs: { api_key: 'WfUR65SA5p1PzpBysgK4' },
          };
          return new Promise(//make the request as promise
            (resolve,reject)=>
              request(options, function (error, response, body) {
                if(err){
                  reject(err);//reject if there is an error
                }
                var obj = JSON.parse(body);
                resolve({//resolve if there is no error
                  "code": obj.dataset.dataset_code,
                  "name": obj.dataset.name,
                  "date": obj.dataset.end_date,
                  "nav": obj.dataset.data[0][1]
                });
              })
          )
          .then(
            result=>{//add result item to results if successfull
              results.push(result);
              return results;
            }
          )
          .catch(
            err=>{//add Fail item to results if failed
              results.push(new Fail([err,mfId]));
              return results;
            }
          )
          .then(
            results=>
              new Promise(//wait for one second to make the next request
                (resolve,reject)=>
                  setTimeout(
                    _=>resolve(results)
                    ,1000
                  )
              )
          )
        }
      )
    ,Promise.resolve([])
  )
//example of how to ue this function
sequentialMF(ids)
.then(
  results=>{
    const successes = results.filter(result=>!isFail(result));
    const failed = results.filter(isFail);
  }
)