1

I would like to add some timeout between below get requests. I mean, flow should be looks like: timeout, https://example.com/example1, timeout, https://example.com/example2, timeout, https://example.com/example3, timeout etc. (or without first timeout, whatever).

Below function is working properly:

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

Where parts is -> example1, example2, example3....

I am trying do it by adding timer:

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

And use it:

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

But it is wrong flow -> timeout, timeout, timeout,..., get request1, get request 2, get request 3.

profiler
  • 567
  • 2
  • 15
  • 41

2 Answers2

2

You may reduce it to a Promise chain:

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

However thats quite ugly, so you may use async / await instead:

 async function promiseGetInformationFromMultipleUrls(parts){
   const result = [];
   for(const part of parts){
     await timer(1000);
     result.push(await request(/*...*/));
  }
  return result;
}
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • The best solution, for me, will be not changing the promise to async process Parts function. The promise from, my question, is only snippet from all script. – profiler Jan 04 '18 at 11:21
  • In first proposal - `parts.reduce((chain, part) =>` where is parts? I would like add each of line to url, but there is no parts. – profiler Jan 04 '18 at 13:09
  • @profiler i dont get you. Could you please rephrase it? – Jonas Wilms Jan 04 '18 at 17:47
  • I am sorry. Regarding to first solution - promise chain. There are nothing about "parts", only part. Where I should slice it and use in request part? – profiler Jan 04 '18 at 19:16
  • @profiler `part` is one element of your `parts` array. – Jonas Wilms Jan 04 '18 at 19:19
  • I know, but where is "parts"? There is no "parts" in Your first solution. Och, or I should use that return in promise.all(parts.map....)? – profiler Jan 04 '18 at 19:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162543/discussion-between-profiler-and-jonas-w). – profiler Jan 04 '18 at 19:28
  • There is possibility to reuturn the promise (or function) in those solution? Still I have error about expecting a function, no object. – profiler Jan 08 '18 at 08:48
  • Ok, I got it! Just use json.stringify. it is working as expected. – profiler Jan 08 '18 at 10:52
0

The following should work:

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");
  }
)
HMR
  • 37,593
  • 24
  • 91
  • 160