Stop code execution when rejecting promise - javascript

I have the following promise-returning function:
function createJourney() {
return new Promise((resolve, reject) => {
// code ...
doOperation((err, data) {
// code ...
return reject('We need to exit now!')
});
// ---> Why is code stil executing here? <---
})
}
Why is the code executing below the reject? When rejecting, I want to stop the execution of the createJourney function.
I am using Bluebird promise.

Imagine
return new Promise((resolve, reject) => {
doThing1()
doOperation(..);
doThing2()
})
there is no reason why doThing2() should not be executed depending on what happens inside doOperation()
doOperation will probably start an asynchronous operation and doThing2 will be called long before reject is called in your example.

Related

Why we are not chaining promises inside each other?

in one of youtube tutorial videos about promises I found following code:
let cleanRoom = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
let removeGarbage = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
let winIcecream = function() {
return new Promise((resolve, reject) => {
resolve();
});
};
cleanRoom().then(function(){
return removeGarbage();
}).then(function() {
return winIcecream();
}).then(function() {
console.log('finished');
})
Why the promises aren't chained like that the every .then word is after the previous promise? I mean, why for example .then is not immediately after removeGarbage() but it is after the cleanRoom().then(), how is it happening that the winIcecream() will run after resolving the removeGarbage promise?
Also do I need to type return declaring every promise like in the code above? If yes, why do I need to do so?
Your initial questions may be answered by rewriting things to variable assignments.
I'm using arrow function syntax to implicitly return the new expression here; if you're using regular functions, then yes, you do have to return the new chained promise if you want to run them in sequence.
const roomCleanedPromise = cleanRoom();
const roomCleanedAndGarbageTakenOutPromise = roomCleanedPromise.then(() => removeGarbage());
const roomCleanedAndGarbageTakenOutAndIcecreamWonPromise = roomCleanedAndGarbageTakenOutPromise.then(() => winIcecream());
const finishedPromise = roomCleanedAndGarbageTakenOutAndIcecreamWonPromise.then(() => console.log('finished'));
However things are easier written using the more modern async/await syntax - the YouTube tutorial you mention is a little outdated, perhaps.
async function cleanRoom() {
console.log('Cleaning room.');
// this could do other async things or just take a while
return {room: 'clean'}; // just to demonstrate a return value
}
async function removeGarbage() {
console.log('Removing garbage.');
// this could do other async things or just take a while
return {garbage: 'removed'};
}
// third function elided for brevity
async function doAllTheThings() {
const roomStatus = await cleanRoom();
const garbageStatus = await removeGarbage();
console.log('finished');
}
The purpose of using a fulfillment handler (the functions passed to then in your example) is to wait for the promise to be fulfilled and then, at that point, do something else.
The goal of that code (apparently) is to wait until the cleanRoom promise is fulfilled, then start the removeGarbage process, and then when that is fulfilled, start the winIcecream process. It's also worth noting that if cleanRoom's promise was rejected instead of being fulfilled, removeGarbage wouldn't happen at all, because it's in a fulfillment handler, not a rejection handler.
If you did this instead:
cleanRoom().then(function() { /*...*/ });
removeGarbage().then(function() { /*...*/ });
winIcecream().then(function() { /*...*/ });
...all three processes would be started immediately and run in parallel (to the extent whatever async process they're modelling can run in parallel with other JavaScript code). There'd be no coordination between them at all.
...how is it happening that the winIcecream() will run after resolving the removeGarbage promise...
then, catch, and finally create and return new promises. Those promises are fulfilled or rejected based on what happens to the promise they were called on and what happens in or is returned by their handler. So for example:
doThis()
.then(function() { return doThat(); })
.then(function() { console.log("done"); });
Let's call the promise from doThis() "Promise A". Calling then on it creates a new promise ("Promise B"), that will either be rejected (if Promise A is rejected) or will call its handler if Promise A is fulfilled. Promise B is resolved to whatever that handler returns. In the code above, suppose Promise A is fulfilled and doThat() returns a promise ("Promise C"). Now, Promise B is resolved to Promise C — whatever happens to Promise C is what will happen to Promise B. If Promise C is fulfilled, Promise B is fulfilled, and the second handler with the console.log is called.
The MDN article on using promises may be helpful.
Your suggestion / thinking I mean, why for example .then is not immediately after removeGarbage() but it is after the cleanRoom().then() is wrong.
Each promise ( .then ) is not execute immediately.
You can take a look at your example ( little edited by me )
const cleanRoom = () => new Promise((resolve, reject) => {
resolve();
});
const removeGarbage = () => new Promise((resolve, reject) => {
resolve();
});
const winIcecream = () => new Promise((resolve, reject) => {
resolve();
})
cleanRoom().then(function(){
console.log('second');
return removeGarbage();
}).then(function() {
return winIcecream();
}).then(function() {
console.log('finished');
})
console.log('first');
You should read more how the event loop works.

Promises - How to make asynchronous code execute synchronous without async / await?

var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
var p3 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
console.log("last to print");
p1.then(()=>p2).then(()=>p3).then(()=> console.log("last to be printed"))
As I was reading about promises, I know that I can print promises synchronous (in this case print: first, second, third, last to print) when I use async /await. Now I have also been reading that the same thing can be achieved using .then chaining and async/await is nothing 'special'. When I try to chain my promises, however, nothing happens except for the console.log of "last to be printed". Any insight would be great! Thanks!!
Edit to question:
var p1 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("first"), 5000);
resolve("first resolved")
});
var p2 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("second"), 2000);
resolve("second resolved")
});
var p3 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("third"), 0);
resolve("third resolved")
});
console.log("starting");
p1.then((val) => {
console.log("(1)", val)
return p2
}).then((val) => {
console.log("(2)", val)
return p3
}).then((val) => {
console.log("(3)", val)
})
Loggs:
starting
(1) first resolved
(2) second resolved
(3) third resolved
third
second
first
1: if executor function passed to new Promise is executed immediately, before the new promise is returned, then why are here promises resolved ()synchronously) first and after the setTimeouts (asynchronously) gets executed?
Return value vs. resolve promise:
var sync = function () {
return new Promise(function(resolve, reject){
setTimeout(()=> {
console.log("start")
resolve("hello") //--works
// return "hello" //--> doesnt do anything
}, 3000);
})
}
sync().then((val)=> console.log("val", val))
The executor function you pass to new Promise is executed immediately, before the new promise is returned. So when you do:
var p1 = new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
...by the time the promise is assigned to p1, the setTimeout has already been called and scheduled the callback for five seconds later. That callback happens whether you listen for the resolution of the promise or not, and it happens whether you listen for resolution via the await keyword or the then method.
So your code starts three setTimeouts immediately, and then starts waiting for the first promise's resolution, and only then waiting for the second promise's resolution (it'll already be resolved, so that's almost immediate), and then waiting for the third (same again).
To have your code execute those setTimeout calls only sequentially when the previous timeout has completed, you have to not create the new promise until the previous promise resolves (using shorter timeouts to avoid lots of waiting):
console.log("starting");
new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 1000);
})
.then(result => {
console.log("(1) got " + result);
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 500);
});
})
.then(result => {
console.log("(2) got " + result);
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 100);
});
})
.then(result => {
console.log("(3) got " + result);
console.log("last to print");
});
Remember that a promise doesn't do anything, and doesn't change the nature of the code in the promise executor. All a promise does is provide a means of observing the result of something (with really handy combinable semantics).
Let's factor out the common parts of those three promises into a function:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
Then the code becomes a bit clearer:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
console.log("starting");
delay(1000, "first")
.then(result => {
console.log("(1) got " + result);
return delay(500, "second");
})
.then(result => {
console.log("(2) got " + result);
return delay(100, "third");
})
.then(result => {
console.log("(3) got " + result);
console.log("last to print");
});
Now, let's put that in an async function and use await:
function delay(ms, ...args) {
return new Promise(resolve => {
setTimeout(resolve, ms, ...args);
});
}
(async() => {
console.log("starting");
console.log("(1) got " + await delay(1000, "first"));
console.log("(2) got " + await delay(500, "second"));
console.log("(3) got " + await delay(100, "third"));
console.log("last to print");
})();
Promises make that syntax possible, by standardizing how we observe asynchronous processes.
Re your edit:
1: if executor function passed to new Promise is executed immediately, before the new promise is returned, then why are here promises resolved ()synchronously) first and after the setTimeouts (asynchronously) gets executed?
There are two parts to that question:
A) "...why are here promises resolved ()synchronously) first..."
B) "...why are here promises resolved...after the setTimeouts (asynchronously) gets executed"
The answer to (A) is: Although you resolve them synchronously, then always calls its callback asynchronously. It's one of the guarantees promises provide. You're resolving p1 (in that edit) before the executor function returns. But the way you're observing the resolutions ensures that you observe the resolutions in order, because you don't start observing p2 until p1 has resolved, and then you don't start observing p3 until p2 is resolved.
The answer to (B) is: They don't, you're resolving them synchronously, and then observing those resolutions asynchronously, and since they're already resolved that happens very quickly; later, the timer callbacks run. Let's look at how you create p1 in that edit:
var p1 = new Promise(function (resolve, reject) {
setTimeout(() => console.log("first"), 5000);
resolve("first resolved")
});
What happens there is:
new Promise gets called
It calls the executor function
The executor function calls setTimeout to schedule a callback
You immediately resolve the promise with "first resolved"
new Promise returns and the resolved promise is assigned to p1
Later, the timeout occurs and you output "first" to the console
Then later you do:
p1.then((val) => {
console.log("(1)", val)
return p2
})
// ...
Since then always calls its callback asynchronously, that happens asynchronously — but very soon, because the promise is already resolved.
So when you run that code, you see all three promises resolve before the first setTimeout callback occurs — because the promises aren't waiting for the setTimeout callback to occur.
You may be wondering why you see your final then callback run before you see "third" in the console, since both the promise resolutions and the console.log("third") are happening asynchronously but very soon (since it's a setTimeout(..., 0) and the promises are all pre-resolved): The answer is that promise resolutions are microtasks and setTimeout calls are macrotasks (or just "tasks"). All of the microtasks a task schedules are run as soon as that task finishes (and any microtasks that they schedule are then executed as well), before the next task is taken from the task queue. So the task running your script does this:
Schedules a task for the setTimeout callback
Schedules a microtask to call p1's then callback
When the task ends, its microtasks are processed:
The first then handler is run, scheduling a microtask to run the second then handler
The second then handler runs and schedules a micro task to call the third then handler
Etc. until all the then handlers have run
The next task is picked up from the task queue. It's probably the setTimeout callback for p3, so it gets run and "third" appears in the console
Return value vs. resolve promise:
The part you've put in the question doesn't make sense to me, but your comment on this does:
I read that returning a value or resolving a promise is same...
What you've probably read is that returning a value from then or catch is the same as returning a resolved promise from then or catch. That's because then and catch create and return new promises when they're called, and if their callbacks return a simple (non-promise) value, they resolve the promise they create with that value; if the callback returns a promise, they resolve or reject the promise they created based on whether that promise resolves or rejects.
So for instance:
.then(() => {
return 42;
})
and
.then(() => {
return new Promise(resolve => resolve(42));
})
have the same end result (but the second one is less efficient).
Within a then or catch callback:
Returning a non-promise resolves the promise then/catch created with that value
Throwing an error (throw ...) rejects that promise with the value you throw
Returning a promise makes then/catch's promise resolve or reject based on the promise the callback returns
You cannot make asynchronous code execute synchronously.
Even async / await are just syntax that gives you a synchronous-style control flow inside a promise.
When I try to chain my promises, however, nothing happens except for the console.log of "last to be printed". Any insight would be great!
The other functions don't generate any output. That has nothing to do with them being in promises.
You start three timers (all at the same time), then log 'last to print', then chain some promises so that 'last to be printed' will print when all three promises resolve (5 seconds after you start them all going).
If you want the timers to run sequentially, then you have to initiate them only when the previous one has finished, and if you want to see what they resolve with then you have to write code that actually looks at that.
function p1() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
}
function p2() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
}
function p3() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
}
function log(value) {
console.log("Previous promise resolved with " + value);
}
p1()
.then(log)
.then(p2)
.then(log)
.then(p3)
.then(log)
.then(() => console.log("last to be printed"));
Async/await is, arguably, neater:
function p1() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("first"), 5000);
});
}
function p2() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("second"), 2000);
});
}
function p3() {
return new Promise(function(resolve, reject) {
setTimeout(() => resolve("third"), 1000);
});
}
function log(value) {
console.log("Previous promise resolved with " + value);
}
(async function() {
log(await p1());
log(await p2());
log(await p3());
console.log("last to be printed");
}());
If you need to call an await but the function that contains that await doesn't have to be async, because you need, for example, a "number" and not a "Promise number ", you can do de next:
var ex: number = new Number(async resolve => {
var f = await funcionExample();
resolve(f);
}).valueOf();

Create a Javascript promise in a dormant state?

One of the issues I have faced when crafting Promises for certain app context is that of wanting to delay any execution of the code inside the promise until later. This happens frequently when I have manager objects that maintain a collection of Promises for execution at a later time. To remedy this, I end up creating builder functions that are called by the manager objects at the time the Promise needs to be executed. This is tedious and leads to a fair amount of "boilerlate" code.
For example, here's one of my Promise builder functions:
this._buildPollingPromise = function(ethTransWaiter) {
return new Promise(function(resolve, reject) {
// Execute the function that builds a polling method promise.
ethTransWaiter.confirmTransPromiseBuilder.buildPromise()
.then(function(result) {
...
})
.then(function(ignoreResult) {
resolve(ethTransWaiter.isConfirmed);
})
.catch(function(err)
{
// Reject the promise with the error received.
reject(err);
});
});
}
I have to delay execution of the ethTransWaiter.confirmTransPromiseBuilder.buildPromise() method because if it executes at the time the Promise is created, it will fail because the conditions aren't in place yet for it to execute successfully.
Therefore, I am wondering if there is a built-in method, or an NPM package, that creates or helps create Promises that can be built in a dormant state, so that the code in the function that lives inside the Promise constructor does not execute until some later time (i.e. - at the precise time when you want it to execute) That would save me a lot of boilerplate coding.
May be something like this?
function wait(ms) {
return new Promise(function (resolve) {
setTimeout(resolve, ms);
});
}
this._buildPollingPromise = function (ethTransWaiter) {
var waitUntilLater = wait(3000);
var buildPromise = new Promise(function (resolve, reject) {
// Execute the function that builds a polling method promise.
ethTransWaiter.confirmTransPromiseBuilder.buildPromise()
.then(function (result) {
//...
})
.then(function (ignoreResult) {
resolve(ethTransWaiter.isConfirmed);
})
.catch(function (err) {
// Reject the promise with the error received.
reject(err);
});
});
return Promise.all([waitUntilLater, buildPromise]).then(function (results) {
return results;
});
}

The batch function passed to the ".run" method didn't return a promise

Although I do realize what the error means and why it happens, I think I have a use case that goes outside the expected. I am using Word.run() inside another promise, like so:
return new Promise((resolve, reject) => {
window.Word.run(context => {
// do stuff with context
resolve(someData);
});
});
So, if I understood it correctly, this resolves my promise, but leaves the .run method hanging since there's no return context.sync() at the end? Or did I get it wrong? If I'm right, how can I rewrite the example above to keep .run working properly?
If you want your promise to resolve after the context syncs...
return new Promise((resolve, reject) => {
window.Word.run(context => {
// do stuff with context
return context.sync().then(function() {
resolve(someData); // promise will resolve after sync resolves
});
});
});
If you don't need to resolve after but just want to sync the context at some point in the future, you can actually do this and it won't wait for the sync:
return new Promise((resolve, reject) => {
window.Word.run(context => {
// do stuff with context
resolve(someData); // this will resolve the promise
return context.sync(); // this will actually still happen since the function never returns
});
});

Using await within a Promise

There seems something inherently wrong with having to define a Promise's callback as asynchronous:
return new Promise(async (resolve, reject) => {
const value = await somethingAsynchronous();
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
});
This is apparently an antipattern and there are coding problems which can arise from it. I understand that it becomes easier to fail to catch errors here, even when placing await statements inside try/catch blocks.
My first question is, what's the best way to code something like this, when one wants to forward a Promise with different resolve/reject values? With then/catch? I.e.
return new Promise((resolve, reject) => {
somethingAsynchronous().then(value => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
}); // errors would now be propagated up
});
Or do you just take it out the Promise constructor altogether as suggested here?
async function outerFunction() {
const value = await somethingAsynchronous();
return new Promise((resolve, reject) => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
});
}
But what if you have several await statements in the outerFunction(), i.e. a linear code block calling several asynchronous functions. Would you then have to create and return a new Promise every time?
But then how do you account for code such as this?
async function outerFunction() {
if (someSynchronousCheck()) {
return 'Nope. Try again.' // another reject case
}
const value = await somethingAsynchronous();
// ...
}
I have the feeling that I'm making this more complicated than it should be. I'm trying to avoid nesting callbacks/chaining then/catch blocks without creating more problems in the future.
My final question is, why is the callback passed to a Promise not inherently async? It is already wrapped within a promise and expects the resolve/reject functions to be called asynchronously.
You do this:
async function outerFunction() {
const value = await somethingAsynchronous();
if (value === something) {
return 'It Worked!';
}
throw Error('Nope. Try again.');
}
Using async wraps the result of outerFunction with a Promise.
If you want that wrapping promise to resolve to something, just return it from the async function. If you want the wrapping promise to be rejected, throw an error inside the async function.
But then how do you account for code such as this?
async function outerFunction() {
if (someSynchronousCheck()) {
throw Error('Nope. Try again.');
}
const value = await somethingAsynchronous();
// ...
}
new Promise(async (resolve, reject) => { ... }) is relatively new antipattern. It results in creating 2 promise objects instead of 1, uncaught errors that happen inside constructor cannot be caught with try..catch and result in unhandled rejection.
Considering that promise asynchronous code can be handled with async..await, current use case for Promise constructor is non-promise asynchronous code, e.g.:
new Promise(resolve => setTimeout(resolve, 1000))
When Promise constructor contains synchronous code or involves other promises, a promise should be constructed with async function. A drop-in replacement is async IIFE:
return (async (resolve, reject) => {
const value = await somethingAsynchronous();
if (value === something) {
return 'It worked!';
} else {
throw 'Nope. Try again.';
}
})();
If the need for Promise constructor still presents when being used together with async, Promise constructor should be moved down in hierarchy so it won't wrap any async function.
My final question is, why is the callback passed to a Promise not inherently async? It is already wrapped within a promise and expects the resolve/reject functions to be called asynchronously.
async function isn't just a function that is executed asynchronously, it returns another promise that is supposed to be utilized - or at least handled with catch. Promise isn't supposed to utilize a promise that is returned from constructing function.
The constructor can resolve on same tick and doesn't necessarily have to be asynchronous.
Promise.resolve(1);
is similar to
Promise(resolve => resolve(1))
and not to
Promise(resolve => setTimeout(() => resolve(1)))
You can also chain the promises yourself by simply doing this:
return new Promise((resolve, reject) => {
somethingAsynchronous().then((value) => {
if (value === something) {
return resolve('It worked!');
} else {
return reject('Nope. Try again.');
}
}, (error) => { reject(error); });
});
I've been using this for some time and it works perfectly for me.

Categories