0

A few days ago, I tried to implement a function to check if a resource is reachable or not. I'm rather new to JS and had to restructure my complete code, to implement the async funtion suggested here on SO.

Now I've got things working as intended, with the above mentioned answer by @adeneo.

However the process takes 2 minutes+, if the resource is unreachable, so I want to implement a timeout for the fetch command.

I came across this answer on a GitHub issue:

var p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
])
p.then(response => console.log(response))
p.catch(error => console.log(error))

I'm really not familiar with JS and am a bit lost here.

How can I implement the timeout as suggested above in the function I've implemented, posted on the SO question I mentioned?

edit:

Since in my case, the fetch('/resource-that-may-take-a-while') is a little more extensive, I've tried to wrap the suggested Promise.race around the working code I already have.

The result is an approach to implement both, the suggested function from the previous SO question and the suggestion from GitHub for a timeout.

function chk(target, times, delay) {
    var p = Promise.race([
    return new Promise((res, rej) => {

        (function rec(i) {
            fetch(target, {mode: 'no-cors'}).then((r) => {
                res(r);
            }).catch( err => {
                if (times === 0)
                    return rej(err);

                setTimeout(() => rec(--times), delay )
            });
        })(times);

    }),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
])
p.catch(error => console.log("timeout"));
}

This results in Uncaught SyntaxError: Unexpected token return for the line return new Promise((res, rej) => {.

Community
  • 1
  • 1
SaAtomic
  • 619
  • 1
  • 12
  • 29
  • You can't return in an array declaration statement. Simply omit the `return` keyword. – Johannes Mar 27 '17 at 13:38
  • I might be wrong, but I think I need to return the promise there, otherwise the complete *inner* function never returns anything. – SaAtomic Mar 27 '17 at 13:42
  • `Promise.race` finishes if either the fetch or timeout promise resolve or reject. The `inner` function (`rec`) is called regardless of your return statement. Further, you can't return anything from the Promise callback - which is the way callbacks work. Use `p.then` to handle the event that the fetch worked. Use `p.catch` (as you already did) to handle the timeout case. – Johannes Mar 27 '17 at 13:49

1 Answers1

1

As per the mdn:

The Promise.race(iterable) method returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects, with the value or reason from that promise.

All you need to do is pass the promises into the array you pass to the Promise.race function. You don't have to return there - but you can return the Promise of the chk function to use it directly as shown below. p resolves/rejects if either chk or the timeout completes/fails

var p = Promise.race([
  chk(t, 3, 1000),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
])

p.catch(error => console.log('timeout'))

function chk (target, times, delay) {
  return new Promise((res, rej) => {
    (function rec (i) {
      fetch(target, { mode: 'no-cors' }).then((r) => {
        res(r)
      }).catch(err => {
        if (times === 0) {
          return rej(err)
        }

        setTimeout(() => rec(--times), delay)
      })
    })(times)
  })
}
Johannes
  • 1,249
  • 3
  • 17
  • 33