Rejecting a Promise by passing a Promise

promise reject
javascript promise w3schools
promise((resolve, reject))
javascript promise then
promise catch
javascript promise resolve
await promise
node.js promise

Why is it exactly that the a resolveing promise correctly waits for the someOtherPromise to complete, but the reject does not? Run the following code sample and check the console.log output. I expected the "myFailingPromise rejected" message to show 2000 ms later, just as the "myPromise resolved" did.

let someOtherPromise = (previousPromise) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(previousPromise + ' => someOtherPromise after 2000ms');
      resolve('someOtherPromise');
    }, 2000);
  });
}

let myPromise = () => {
  return new Promise((resolve, reject) => {
    resolve(someOtherPromise('myPromise'));
  });
};

let myFailingPromise = () => {
  return new Promise((resolve, reject) => {
    reject(someOtherPromise('myFailingPromise'));
  });
};

myPromise().then((val) => {
  // this is executed after `someOtherPromise` resolves.
  console.log('myPromise resolved');
}).catch((err) => {
  console.log('myPromise rejected');
});

myFailingPromise().then((val) => {
  // this is executed after `someOtherPromise` resolves.
  console.log('myFailingPromise resolved');
}).catch((err) => {
  console.log('myFailingPromise rejected');
});

When you're resolving a promise A, if the value with which you're resolving it is a promise B, then your promise A will match the state of the promise B.

However, when you're rejecting a promise, your only giving a reason, whether the reason looks or not like a promise doesn't matter.

What you need to do, is to resolve with someOtherPromise in both cases.

If you want to wait for the first promise and reject anyway, you can do this:

let myFailingPromise = () => {
  return new Promise((resolve, reject) => {
    someOtherPromise.then(reject);
  });
};

Using Promises, Unlike "old-style", passed-in callbacks, a promise comes with some guarantees: Whenever a promise is rejected, one of two events is sent to the global scope  Rejecting a Promise means that the Promise becomes rejected. Resolving a Promise has different effects, depending on what value you are resolving with: Resolving with a normal (non-thenable) value fulfills the Promise.

The reject only takes in a reason to highlight the error. Not another promise. You can resolve a promise with another promise of the same type, yet only the last promise's success case you will see.

Have a look at this adapted implementation:

const someOtherPromise = new Promise((resolve, _) => {
    resolve("I am a success");
});
const failingPromise = new Promise((_, reject) => {
    reject("I failed for a reason");
});

someOtherPromise
    .then((result) => {
            console.log("some other promise resolves", result);
            failingPromise
                .then((success) => {
                    console.log("never called");
                })
                .catch((reason) => {
                    console.error("failing promise rejects", reason);
                });
        }
    )
    .catch((error) => {
        console.error("also never called", error);
    });

This is the then-able approach to wait for other promises leading to a callback hell. This is why you can also use async / await syntax:

const app = async () => {
        try {
            const success1 = await someOtherPromise; // will succeed
            console.log(success1);
            const success2 = await failingPromise; // never succceds
            console.log(success2); // never be reached
        } catch (e) {
            return Promise.reject(e); // catches the error of failing promise and rethrows it, redundant but here showcases error handling
        }
    }
;

app()
    .then(() => {
        console.log("never be reached because of failing promise");
    })
    .catch(console.error);

Promise, let promise = new Promise ( function ( resolve , reject ) { // executor (the producing code, "singer") } ) ;. The function passed to new Promise is  Passing multiple arguments in promises How to pass multiple values from one promise step to the next one without lexical scope or global variables. Promises are really simple to use when passing a single argument from the first operation to the next one.

In regards to your updated question with the timeout, here is what you could do in order to always await another promise:

const otherPromise = async (willBeSuccesful: boolean) => {
    console.log("started timer for case", willBeSuccesful);

    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log("resolve timer for case", willBeSuccesful);

            const successValue = "Fnord"; // whatever you want

            return willBeSuccesful
                ? resolve(successValue)
                : reject("this other promise failed because of reasons"); // only provide a reason, not another promise
        });
    };
};

const alwaysWaitForOtherPromiseThenRejectAnyway = async (otherPromise) => {
    try {
        const success = await otherPromise; // always waits 2 seconds, not matter
        console.log("other promises succeeded with value", success);
    } catch (e) {
        return Promise.reject(e); // passing through reason, redundant, only to showcase
    }

    return Promise.reject("reason why this promise failed"); // only happens after otherPromise was resolved, you could swallow that error and fail here or resolve here as well
};

const succeedingPromise = otherPromise(true);
const failingPromise = otherPromise(false);

alwaysWaitForOtherPromiseThenRejectAnyway(succeedingPromise)
    .catch((reason) => console.error(reason)); // fail after waiting for success of other promise

alwaysWaitForOtherPromiseThenRejectAnyway(failingPromise)
    .catch((reason) => console.error(reason)); // will fail as soon as otherPromise fails

It will always wait for the timeout before rejection happens. Rejection will have different reasons. Output will be:

started timer for case true
started timer for case false
resolve timer for case true
resolve timer for case false
other promises succeeded with value Fnord
reason why this promise failed
this other promise failed because of reasons

Rejecting a Promise by passing a Promise, When you're resolving a promise A, if the value with which you're resolving it is a promise B, then your promise A will match the state of the  resolve() and reject() are functions that you call to fulfil or reject the newly-created promise. In this case, the promise fulfills with a string of "Success!". So when you call this promise, you can chain a .then() block onto the end of it and it will be passed a string of "Success!". In the below code we simply alert that message:

Promises: resolve is not the opposite of reject, When I first started working with promises I had the overly simplistic view that passing a value into reject would mark the promise as "failed",  The Promise.reject() method returns a Promise object that is rejected with a given reason. The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

JavaScript Promises: An introduction, var promise = new Promise(function(resolve, reject) { Also, be aware that jQuery doesn't follow the convention of passing Error objects into  All promises above are rejected. When you resolve a value with a "then" method, you're deferring the resolution to the eventual non-promise value. In Practice. You can resolve a value without worrying if it's a value, a promise, or a promise that resolves to a promise that resolves to a promise etc etc.

Master the JavaScript Interview: What is a Promise?, A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise When I reject() with a value, I always pass an Error object. Generally I​  And an immediately rejected Promise by using the Promise.reject() method, like so: let promise = Promise.reject('fail'); One of the nice things about Promises is that if we add a then handler after the promise resolves or rejects the handler still gets called.

Comments
  • That's simply how resolve and reject work. resolve is not fulfill (unfortunately).
  • Your new Promise in myPromise resolves right away with the someOtherPromise. So myPromise().then() is actually only the success handler for someOtherPromise. What are you trying to achieve here?
  • ive updated the question with a proper sample
  • resolveing both cases is not the correct way when there is a catch waiting for a failed case. If i want to reject that promise with a promise, I'd have to call someOtherPromise.then(reject) (which works). My question is: why is reject(someOtherPromise) not supported
  • @Flame Update your usa-case in your question. This sounds like a XY-problem to me. Why do you want to reject a promise with another promise (which isn't supported by design)?
  • @k0pernikus i simply want to reject a promise which waits for the passed promise to fulfill. If the answer is "its not supported by design" or "a reject is not supposed to contain a promise" then that doesnt answer the question since you're basically saying "you cant because you cant".
  • resolve(someOtherPromise.then(() => throw new Error("reject")))
  • your updated answer calls then(reject()) but it should be then(reject) otherwise it immediately executes i believe
  • does something go inherently wrong when promises will support a rejection with a promise as its argument? I am wondering why it doesnt follow the resolve spec.
  • You can resolve with any type. It can be a string, number, object, and also a promise or a collection of a promise -- whatever you fancy as a success case for your Promise. Rejections only handle a reason, that will be either a string message or an Error. Rejections are not supposed to contain other Promises.
  • @Flame If reject did assimilate promises, then how would it be different from resolve? (In fact, reject isn't necessary at all. We could do only with resolve, and use resolve(Promise.fulfill(value)) or resolve(Promise.reject(reason)) to distinguish between success and error cases.)
  • i am envisioning resolve(myPromise) will result in a then() or catch being called afterwards (depending on myPromise result), but a reject(myPromise) will result in a catch() being called afterwards. Note that in both cases it should wait for myPromise to succeed/fail