将计时器添加到Promise.all,map

时间:2018-01-04 11:09:32

标签: javascript node.js get promise request

我想在下面的get请求之间添加一些超时。我的意思是,流程应该看起来像:timeout, https://example.com/example1, timeout, https://example.com/example2, timeout, https://example.com/example3, timeout等(或没有首先超时,无论如何)。

以下功能正常运行:

function promiseGetInformationFromMultipleUrls(parts) {
    return Promise.all(parts.map(part => {
      return request({
            'url': `https://example.com/${part}`,
            'json': true
        }).then(partData =>  {console.log("Part data was fetched: " + part); return partData.result;})
          .catch(err => {console.error("Error during fetching data from part: " + part + ", error code: " + err.statusCode);});
    }));
}

其中部分是 - > example1,example2,example3 ....

我正在尝试添加计时器:

const timer = ms => new Promise( res => setTimeout(res, ms));

并使用它:

function promiseGetInformationFromMultipleUrls(parts) {
    return Promise.all(parts.map(part => {
    console.log("wait 1 seconds");
    timer(1000).then(_=>console.log("done"));
      return request({
            'url': `https://example.com/${part}`,
            'json': true
        }).then(partData =>  {console.log("Part data was fetched: " + part); return partData.result;})
          .catch(err => {console.error("Error during fetching data from part: " + part + ", error code: " + err.statusCode);});
    }));
}

但这是错误的流程 - > timeout, timeout, timeout,..., get request1, get request 2, get request 3

2 个答案:

答案 0 :(得分:2)

您可以将其缩减为Promise链:

function promiseGetInformationFromMultipleUrls(parts) {
 return parts.reduce((chain, part) =>
  chain.then((result) =>
    timer(1000).then(() => 
      request(/*...*/).then(res => 
        result.concat(res)
      )
    )
  ),
  Promise.resolve([])
);
}

然而这很难看,所以你可以使用async / await来代替:

 async function promiseGetInformationFromMultipleUrls(parts){
   const result = [];
   for(const part of parts){
     await timer(1000);
     result.push(await request(/*...*/));
  }
  return result;
}

答案 1 :(得分:0)

以下内容应该有效:

const Fail = function(reason){this.reason=reason;};
const isFail = x=>(x&&x.constructor)===Fail;
const timedoutPromise = time => promise => 
  Promise.race([
    promise,
    new Promise(
      (resolve,reject)=>
        setTimeout(
          x=>reject("timed out"),
          time
        )
    )
  ]);

utls = [];//array of urls
in5Seconds = timedoutPromise(5000);
Promise.all(
  urls.map(
    url=>
      in5Seconds(makeRequest(url))
      .catch(e=>new Fail([e,url]))//failed, add Fail type object
  )
)
.then(
  results=>{
    const successes = results.filter(x=!isFail(x));
    const failed = results.filter(isFail);
    const timedOut = failed.filter(([e])=>e==="timed out");
  }
)