Nested Promise with setTimeout

2019-07-23 07:38发布

问题:

I have a nested promise. The promise resolves or rejects based on another promise resolving or rejecting with a setTimeout of 0 so as not to clog:

  return new Promise((resolve, reject) => {
    promiseInst
    .then(value => {
      executeSoon(() => {
        dispatch({ ...action, status: "done", value: value });
        resolve(value);
      });
    })
    .catch(error => {
      executeSoon(() => {
        dispatch({
          ...action,
          status: "error",
          error: error.message || error
        });
        reject(error);
      });
    });
});

the executeSoon() is executeSoon(fn) { setTimeout(fn, 0); }

How do I simplify this? Tried to get rid of the outer promise wrapper and returning the inner promise directly but got stuck with the resolve and reject not being defined. So I thought I'd just return a Promise.resolve(value) from inside the .then and Promise.reject(error) from the catch, but this does not work either. I feel it might be possible to simplify this, but can't quite get my head around it.

回答1:

Just use a promising timer:

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

Then its as simple as:

  timer(0).then(() => promiseInst)
   .then(...)
   .catch(...)

.... but actually you dont need the timer as promises are guaranteed to resolve one tick after resolve() was called.



回答2:

Remember that a then handler is always executed asychronously, there's no need for setTimeout(..., 0) in the normal case. So if the setTimeout doesn't have another purpose:

return promiseInst
    .then(value => {
        dispatch({ ...action, status: "done", value: value });
        return value;
    })
    .catch(error => {
        dispatch({ ...action, status: "error", error: error.message || error });
        throw error;
    });

If it does something important, I'd probably have a promise-enabled version, something along these lines:

const setTimeoutPromise = (delay = 0) => new Promise(resolve => {
    setTimeout(resolve, delay);
});

Then see the lines with *** below:

return promiseInst
    .then(value => setTimeoutPromise().then(() => value) // ***
    .then(value => {
        dispatch({ ...action, status: "done", value: value });
        return value;
    })
    .catch(error => setTimeoutPromise().then(() => {     // ***
        dispatch({ ...action, status: "error", error: error.message || error });
        throw error;
    })); // <== *** Note one more )