1

I want to reject a promise which I do not built. That is, examples I've read describe something like it:

const sample = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('fail promise');
    }, 1000);
});

That reject the sample after 1s. In my case the promise I want to reject is coming as an external api call then I can't to reject in that way.

Another approaches I've read shows how the promise can be wrapped with other that uses a setTimeout to reject the new promise. Something like this:

const timeout = new Promise(function(resolve, reject) {
    setTimeout(resolve, 1000, 'one');
});

const sample = new Promise(function(resolve, reject) {
    setTimeout(resolve, 5000, 'two');
});

return Promise.race([sample, timeout]);

That force to 'reject' sample after 1s returning the other promise. That could be used to set a timeout but in fact it does not reject sample, only returns another promise and the original continues running until it rejects or resolve itself.

I can not find how can I reject correctly a promise without a library

5
  • You can't reject someone else's promise. Promises are designed that way on purpose. Only the creator of the promise with access to the promise executor function can resolve or reject it. Instead, use their result (whatever it is) and then create your own outcome from that. Commented Jan 17, 2020 at 19:36
  • Thank you for your answer, let me know please if found a place where it is documented. In fact, I am according with you since resolve/reject methods are only allowed during promise creation but I would know if it is documented in someplace, I was looking for that but I did not have good luck to find it. Commented Jan 17, 2020 at 20:23
  • 2
    Well, the functions to resolve and reject and promise are passed to the promise executor and they are NOT methods on a promise. That means they are only available to the code inside the executor callback function unless that callback somehow makes them available to the outside world. I can only point you to the promise documentation that shows where the resolve() and reject() functions are passed and you will see they are ONLY available to that callback. The public methods on a promise are .then(), .catch() and .finally(). Commented Jan 17, 2020 at 20:37
  • FYI, 99.9999% of the time the existing promise model works just fine and you can resolve or reject a promise from within the executor callback function. Very occasionally, you want to be able to control your own promise from outside that callback. This piece of code shows how you can create your own Deferred object from a regular promise which can then be resolved or rejected from outside the executor. You will generally not need this and can do this only on your own promise. Commented Jan 17, 2020 at 20:42
  • 90% of the answer is in the question. 1. Make sure the 'timeout' Promise rejects; 2. Chain from the Promise returned by Promise.race() ie return Promise.race([sample, timeout]).then(data => doSomethingWith(data)).catch(error => /* timeout or other error from earlier in the chain will end up here */). In practice .then().catch() may well be chained to the function call in the caller. Commented Jan 17, 2020 at 20:47

2 Answers 2

1

Why do you need to reject their promise? What you care about is getting a useful result for your code, so write code that gets you that result instead.

Wrap the API call in your own promise, with a timeout rejection on your promise, and a pass-through resolve if that API yields a result before the timeout:

const attempt = new Promise( (resolve, reject) => {
  // run the actual API _and_ your rejection timeout concurrently:
  let rejected = false;

  const id = setTimeout(() => {
    rejected = true;
    reject(new Error('timeout');
  }), 1000);

  actualApiCall(some, input, args, here)
    .then(result => {
      if (rejected) return; // <- if we rejected via timeout, we no longer care.
      clearTimeout(id);     // <- always remember to properly clean up
      resolve(result);
     })
    .catch(e => {
      if (rejected) return;
      clearTimeout(id);
      reject(e)
    });
});

attempt
  .then(result => doSomethingWith(result))
  .catch(e => console.log('rejected:', e));
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer. Your code allow to continue doingSomethingWith(...) after wait 1s. That is fine, but the promise from actualApiCall continues running until it resolve or reject itself. Even tough it will not does anything because rejected=true it could continue running for longtime. In my case, after "reject" (with your approach) I'll call again several times actualApiCall with another parameters and same behavior could succeed again.
I'm using this to replay a playlist. If a video required lot of time to start then go to next one. I'm using videoJS and the problem is that play() method returns a promise that is resolved/rejected internally without a custom control. With your approach I can to load another video but in fact the play() promise continues running. During testing I saw that after lot of rejects (using a similar approach) CPU grows too
Then this is where I say "If that's the problem, why did not you put that in your post so that people can actually comment on that problem"? Please update your post to mention the specific library you're trying to work with, and remember to update your tags accordingly, too.
My question is something general, I tried to give you a use case only to figure out the useful of this question. That is, the problem I described is not specific for the library I gave you as example.
It actually is specific to that library. This is a claissical X/Y Problem. Your assumption is wrong: You want to abort a task. However this is not part of the Promise API. So your library needs to have a different way to cancel something.
0

I can not find how can I reject correctly a promise without a library

First of all, this doesn't seems a good approach to me, even though you can do the following,

const apiPromise = externalApi();

Now apiPromise can either be in resolved or rejected state. In both cases you can throw an error like,

const rejectedPromise = apiPromise.then(
  (fulfilledValue) => { throw "error" },
  (rejetedValue) => { throw "error" }
);
rejectedPromise.catch(err => console.log(err)); //logs "error"

Read more on Promise.then()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.