Program - 1
new Promise(resolve => {
resolve('1');
Promise.resolve().then(() => console.log('2'));
}).then(data => {
console.log(data);
}); // output 2 1
Program -2
new Promise(resolve => {
Promise.resolve().then(() => {
resolve('1');
Promise.resolve().then(() => console.log('2'));
});
}).then(data => {
console.log(data);
}); // output 1 2
I am really confused with the output of both the programs. Can anyone please tell me how the execution thread works here?
What is hard to understand is that resolve doesn't work the same way as return. Creating Promises actually creates a new async context. Everything inside the first function of the Promise is executed synchronously. Then the .then() methods are called with the values resolved synchronously or asynchronously.
In the first example, you resolve '1', but then you create a new Promise with Promise.resolve() and you call the .then() right away. Because the new Promise is inside the first one, everything is called synchronously.
new Promise(resolve => {
resolve('1'); // Will be accessed in the .then() after then end of the callback
Promise.resolve().then(() => log('2')); // called before the end of the function
// because the context is not yet created
}).then(data => {
log(data);
}); // output 2 1
The second example is way harder. You actually create a Promise inside the first Promise and call its resolve right away. The order of execution will be:
first everything in the initial callbacks
After that, create sort of eventListeners from the resolve to the .then
When a resolve is called, execute the callback in .then
There is nothing in the initial function of the nested promise. So it goes straight to the then. The .then() calls the initial resolve(). Here, the kind of eventListener is created so we jump to the initial callback. Then we go back and execute the rest of the function.
new Promise(resolve => {
// Because we call resolve right away, the context of the original promise
// is created
Promise.resolve().then(() => {
resolve('1'); // Calling resolve jumps us to the .then
Promise.resolve().then(() => log('2')); // We execute after.then
});
}).then(data => {
log(data);
}); // output 1 2
If you removed the .resolve(), it would work like the first one:
new Promise(resolve => {
new Promise(() => {
resolve('1');
Promise.resolve().then(() => log('2'));
});
}).then(data => {
log(data);
}); // output 2 1
The difference lies in the context that the event loop is in when resolving the promise (resolve(1)).
There are 2 queues that execute code in JS:
microtask Q
macrotask Q
JS executes a microtask and then runs all the tasks from the macrotask Q (if any)
When resolving a promise from the executor (Promise(...)) you are running inside the macrotask Q. Code executed from inside a promise callback is executed on the microtask Q.
The difference that matters in this case is that when running from inside the microtask Q if you add other microtask (promise callbacks are microtasks) they get added to the current Q and get processed during this queue run.
This is what happens in case no 2, you are resolving the promise from inside a microtask Q, this ends up resolving the top level Promise and add the .then(data => { log(data); }); to the current microtask Q. So the callback will get executed in this run. On the other hand, the handlers of the nested promise Promise.resolve() is not executed now, as handlers are always called async.
Note: it is possible to add microtasks ad infinitum from inside the microtask Q, blocking the execution.
Related
I have a code:
async function hh(){
const promise1 = new Promise((resolve,reject) => {
resolve("First promise");
});
const promise2 = new Promise((resolve,reject) => {
resolve("Second promise");
});
promise2.then((a)=>console.log(a));
console.log(await promise1);
console.log("sync call");
}
hh();
result of this code is:
Second promise
First promise
sync call
My first question why sync call is not on the first place?
Then I just deleted from the code console.log(await promise1);
So the code looks like this:
async function hh(){
const promise1 = new Promise((resolve,reject) => {
resolve("First promise");
});
const promise2 = new Promise((resolve,reject) => {
resolve("Second promise");
});
promise2.then((a)=>console.log(a));
console.log("sync call");
}
hh();
End result now is:
sync call
Second promise
So now sync call is on the first place, just beacuse I deleted the second call, why?
This is what happens in that code:
First version
promise1 and promise2 are promises in status fulfilled -- you could have used the Promise.resolve function instead of new Promise.
promise2.then() registers a callback to be executed when the promise is fulfilled, which it is, so the callback is enqueued as a job in the promise job queue.
await promise1 suspends the hh function and registers hh to be resumed when the promise is fulfilled, which it is, so the resume of hh is enqueued as a job in the promise job queue (which now has two entries).
hh() returns a promise (that is ignored) and the JS call stack becomes empty. Now the event loop will extract the first job and execute it. This outputs "Second promise".
Then the call stack is empty again. The event loop will extract the last job and execute it. This resumes the hh execution context, which executes the console.log and outputs "First promise". It then continues with "sync call". Note that these two console.log are executed in one synchronous sequence, so there is absolutely no way that they could have their outputs in a different relative order.
Second version
Here the await is missing, so there is no suspension of the hh execution context, and the promise job queue only has one entry.
As hh will run to completion the output "sync call" is the first output -- no job got a chance to run yet.
When hh() returns the JS event loop will pick up that one job and executes it. This is the callback that outputs "Second promise".
For the first question:
since promise1 and promise2 are resolved as soon as they are initialized, they will be in `resolved' state
in your code you call promise2.then(a=> console.log(a)) i.e. a=> console.log(a) will be pushed to a (asynchronous) execution task (asynchronous by fulfilled) later when this string function is complete
but now all hh functions are waiting for promise1<fulfilled> to finish so the default console.log(await promise1) and console.log('sync call') will become default synchronous functions with promise1
ending hh
and the function hh ends the synchronous execution continue to execute the waiting tasks now because the promise2 execution task added before it will be completely separated from the waiting task of hh it will be javascript executes because it is prepended resulting in the first function a => console.log(a) being executed
finish the task of promise2 continue to promise1 it works as synchronous code
Regarding the 2nd question
as I explained earlier a => console.log(a) is added to the task (asynchronously ready run by fulfilled) and hh does not depend on it leading to the next synchronous function continue executing console.log('sync call') then hh completes it continues executing promise2 task
then you call await promise1 it will also put the whole block of code afterwards (like you called .then above) into a task that executes (asynchronously)
This is achieved because javascript is a single-threaded language:
https://dev.to/bbarbour/if-javascript-is-single-threaded-how-is-it-asynchronous-56gd#:~:text=Javascript%20is%20a%20single%20threaded,times%20that%20can%20be%20harmful.
you can also achieve the above by using asynchronous functions like setTimeout...
More information at: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing
Your promises are already resolved when your code reaches the last three operations. So, .then() is being called for promise2 and that schedules it to be picked up by the event loop once the current function is executed and this will happen under normal circumstances, this is why your second example first displays "sync call" and only then "Second Promise".
Yet, your await ensures that the current function is paused which allows the event loop to pick up the .then() of promise2 and evaluate the results of promise1. If you invert the order of your first and second line of the last three, then you get "First promise", "Second promise" and "sync call" being displayed.
async function hh(){
const promise1 = new Promise((resolve,reject) => {
resolve("First promise");
});
const promise2 = new Promise((resolve,reject) => {
resolve("Second promise");
});
console.log(await promise1);
promise2.then((a)=>console.log(a));
console.log("sync call");
}
hh();
A simple conversion of your initial code block into code that doesn't use async/await probably shows why console.log("sync call") isn't executed first.
async function hh(){
const promise1 = new Promise((resolve,reject) => {
resolve("First promise");
});
const promise2 = new Promise((resolve,reject) => {
resolve("Second promise");
});
promise2.then((a)=>console.log(a));
console.log(await promise1);
console.log("sync call");
}
hh();
function hh(){
const promise1 = new Promise((resolve,reject) => {
resolve("First promise");
});
const promise2 = new Promise((resolve,reject) => {
resolve("Second promise");
});
promise2.then((value) => console.log(value));
return promise1.then((value) => {
console.log(value);
console.log("sync call");
});
}
hh();
The above should give you a clear picture of why console.log("sync call") is not logged first.
Everything after an await becomes part of a then() callback, since the function is paused until the promise resolves. Statements are executed in sequential order, so console.log("sync call") can only be executed after console.log(await promise1).
console.log(a);
console.log(await promiseB);
console.log(c);
console.log(d);
console.log(await promiseE);
console.log(f);
console.log(await promiseG);
Can be written as:
console.log(a);
promiseB.then((b) => {
console.log(b);
console.log(c);
console.log(d);
return promiseE;
}).then((e) => {
console.log(e);
console.log(f);
return promiseG;
}).then((g) => {
console.log(g);
});
FIRST QUESTION ANSWER : You have suspended the Program's Execution by using the following line --> console.log(await promise1) until promise1 either gets resolved or rejected. During this suspended phase, the JS callstack is empty and the promise2 was already resolved and moved to the micro queue. Now, here comes the event loop. Event Loop sees that since the Callstack is empty, I should put whatever is present in my micro queue to the JS callstack and puts promise2's result (Second promise) to the call stack and it gets printed first and JS call stack becomes empty. Now,as you have suspended the execution of the code until promise1 resolves, First promise gets moved to the micro queue and again since the call stack is empty, Event Loop places the promise1's result on the call stack and First promise gets printed. After this, JS Single Thread moves to the next line and you see the sync call as your last printed statement
SECOND QUESTION ANSWER: The line promise2.then((a)=>console.log(a)); is asynchronus in nature, JS Single thread moves to the next line and push this line (console.log("sync call");) to the JS callstack. During this process, promise2 gets resolved and is moved to the Micro Queue. BUT Event Loop waits untill JS Call Stack is empty and will only push the promise2's result on the Call Stack, when console.log("sync call"); get executed and poppes out of the call stack. That's why you see sync call first and then,Second promise.
SYNOPSIS:
In Node.js event queues, and code like "new Promise((r) => setTimeout(r, t));", is the setTimeout() evaluated NOW, in the microqueue for Promise resolves, or where?
DETAILS:
I'm reading through Distributed Systems with Node.js (Thomas Hunter II, O'Reilly, 3rd release of First Edition). It tells me that Node.js goes thru each queue in turn:
Poll: for most things, including I/O callbacks
Check: for setImmediate callbacks
Close: when closing connections
Timers: when setTimeout and setInterval resolve
Pending: special system events
There are also two microqueues evaluated after each queue is empty, one for promises and one for nextTick().
On the book's p.13 he has an example where an await calls a function that returns "new Promise((r) => setTimeout(r, t));". The book code is:
const sleep_st = (t) => new Promise((r) => setTimeout(r, t));
const sleep_im = () => new Promise((r) => setImmediate(r));
(async () => {
setImmediate(() => console.log(1));
console.log(2);
await sleep_st(0);
setImmediate(() => console.log(3));
console.log(4);
That is,
setImmediate(() => console.log(1));
console.log(2);
Promise.resolve().then(() => setTimeout(() => {
setImmediate(() => console.log(3));
console.log(4);
This is what I think is going on:
The program starts with a task in the Poll queue, the p.13 code. It starts running.
The Check queue gets a task and the "2" printed to the console.
The "await sleep_st(0)" will have called setTimeout, which puts a
task on the Timer queue. Since the timeout is zero, by the time we
access the Timer queue there will be work to do. The sleep_st(0)
returns a Promise.
This ends the work of the Poll queue.
Now the result micro queue starts. My code resumes executing. This should start with
setImmediate() and console.log(4).
This means that the output to the console is "2 4". However, the book says the proper sequence is "2 1 4 3". That is, the event queue for Check, and perhaps Timer, gets involved.
What, then, happens in the promise result microqueue?
In Node.js event queues, and code like "new Promise((r) => setTimeout(r, t));", is the setTimeout() evaluated NOW, in the microqueue for Promise resolves, or where?
The call to setTimeout is evaluated "now." (The setTimeout callback is called later as appropriate, during the time phrase.) When you do new Promise(fn), the Promise constructor calls fn immediately and synchronously, during your call to new Promise(fn). This is so the function (called an executor function) can start the asynchronous work that the promise will report on, as your two examples (one starts the work by calling setTimeout, the other by calling setImmediate.)
You can easily see this with logging:
console.log("Before");
new Promise((resolve, reject) => {
console.log("During");
setTimeout(() => {
console.log("(fulfilling)");
resolve();
}, 10);
})
.then(
() => {
console.log("On fulfillment");
},
() => {
console.log("On rejection");
}
);
console.log("After");
That logs
Before
During
After
(fulfilling)
On fulfillment
because
It calls console.log("Before"); before doing anything else.
It calls new Promise and log console.log("During"); synchronously in the callback.
It calls console.log("After"); after creating the promise and adding fulfillment and rejection handlers to it.
It calls console.log("(fulfilling)"); when the timer fires and fulfill the promise.
It calls console.log("On fulfillment"); when the fulfillment handler is called.
On your notes on the sequence:
The "await sleep_st(0)" will have called setTimeout
Just to be really clear, it's specifically the sleep_st(0) part that called setTimeout. All await did was wait for the promise sleep_st returned after calling setTimeout to settle.
You may find this example useful, see inline comments:
const sleep = ms => new Promise(resolve => {
// Happens immediately and synchronously when `sleep` is called
console.log("calling setTimeout");
setTimeout(() => {
// Happens later, during the timer phase
console.log("fulfilling promise");
resolve(); // <=== If there are any attached promise handlers,
// this queues calls to them in the microtask
// queue, to be done after this "macro" task
// running in the timer phase is complete
}, ms);
});
const example = async (label) => {
// Happens synchronously and immediately when `example` is called
await sleep(0);
// Happens in a microtask queued by the fulfillment of the promis
console.log(`Sleep done: ${label}`);
};
(async () => {
await Promise.all([example("a"), example("b")]);
// Happens in a microtask queued by fulfillment of the `Promise.all`
// promise
console.log("All done");
})();
The output is:
calling setTimeout
calling setTimeout
fulfilling promise
Sleep done: a
fulfilling promise
Sleep done: b
All done
Note how the code for Sleep done: a was executed between the two tasks for the timer callbacks, because those timer callbacks are "macro" tasks and promise fulfillment callbacks are queued as microtask to be run at the end of the current macrotask.
by the time we access the Timer queue there will be work to do
Before get to timer phase, there is check phase, so "1" is printed before "3",
but i exectued the code on my window, the result is 2 4 1 3, that is setTimeout and setImmediate will race for exectued, sometime setTimeout first, sometile second, i executed the example code in this book for many time in a short time
I've written a small program that compares the fulfillment of promises between the .then() approach and the async/await approach. The code runs correctly, however, the output was received in an unexpected order. Can someone please explain why the output is in its current order?
const backend = (num) => {
const someVar = new Promise((resolve, reject) => {
if (num % 2 === 0) {
resolve(`The number, ${num}, is even.`);
} else {
reject(`The number, ${num}, is odd.`);
}
})
return someVar;
}
const builtInFuncs = (num) => {
backend(num)
.then(message => console.log(message))
.catch(message => console.log(message));
}
const asyncAwait = async(num) => {
try {
const response = await backend(num);
console.log(response);
} catch (error) {
console.log(error);
}
}
builtInFuncs(2);
builtInFuncs(3);
asyncAwait(4);
asyncAwait(5);
The output I expected is:
The number, 2, is even.
The number, 3, is odd.
The number, 4, is even.
The number, 5, is odd.
The output I receive is:
The number, 2, is even.
The number, 4, is even.
The number, 5, is odd.
The number, 3, is odd.
For microtask resolution, each method call is queued separately. So the order of execution is this:
First call enqueued
Second call enqueued
Third call enqueued
Forth call enqueued
First .then fires, console.logged.
Second .then fires, rejection, .catch handler enqueued (NOT called).
Call in async/await, console.logged
Second call to async/await, rejection, catch block enqueued.
The .catch resolves, console.logged.
The catch block resolves, final log.
Props to Barmar in the comments about the idea of switching the order of the catch and then.
To illustrate a little more simply (clearly?), consider a counter and a Promise function that increments and then decrements it:
let i = 0;
const log = Promise.resolve()
.then(() => console.log(++i))
.then(() => console.log(--i));
log();
log();
This will print 1 2 1 0 instead of 1 0 1 0. And if you think about it, this makes a certain amount of sense: the method chain might fail at any step so the runtime enqueues the first call and the second .then only gets enqueued once the first finishes. Otherwise if the first call failed (rejected) it would have to go back and delete the speculatively enqueued second call from the callback queue.
Before we get to the answer, it is worth mentioning that relying on the order of execution of asynchronous calls is not a good practice. There are two ways to achieve your expected behavior. The preferred method should be:
(async() => {
await builtInFuncs(2);
await builtInFuncs(3);
await asyncAwait(4);
await asyncAwait(5);
})();
Alternatively, you may rely on the execution order of PromiseReactionJobs guaranteed by ECMAScript Standard. You need to redefine builtInFuncs as:
const builtInFuncs = (num) => {
backend(num).then(
message => console.log(message),
message => console.log(message)
);
}
Note that both onFulfilled and onRejected handlers are passed to .then() function.
The actual reason for the observed sequence of execution is pretty involved but here is what happens:
builtInFuncs(2) gets invoked
builtInFuncs(2) invokes backend(2).then()
backend(2).then() in effect enqueues console.log(2)
backend(2).then() returns a promise (say promise1)
backend(2).then().catch() notes the onRejected handler on promise1 object
builtInFuncs(3) gets invoked
builtInFuncs(3) invokes backend(3).then()
backend(3).then() enqueues a dummy onRejected handler bacause none is specified
backend(3).then() returns a promise (say promise2)
backend(3).then().catch() notes the onRejected handler that calls
console.log(3) on promise2
asyncAwait(4) gets invoked
asyncAwait(4) effectively invokes backend(4).then()
backend(4).then() enqueues a onFulfilled handler that continues try branch
asyncAwait(5) gets invoked
asyncAwait(5) effectively invokes backend(5).then()
backend(5).then() enqueues a onRejected handler that continues catch branch
handler that prints console.log(2) gets dequeued
dummy onRejected handler gets dequeued
promise2 enqueues onRejected handler it noted which prints console.log(3)
onFulfilled handler that continues try branch gets dequeued
onRejected handler that continues catch branch gets dequeued
handler that prints console.log(3) gets dequeued
Note that the promise that backend returns is immediately resolved or rejected. If not, there are more steps involved but effectively the same behavior is observed.
I don’t understand why this piece of code results in such an order? Could anyone elaborate on this? I thought Promises were like a FIFO queue, but the nested Promise functions seems a little bit unpredictable, or maybe using some other data structure?
new Promise(resolve => {
resolve()
})
.then(() => {
new Promise(resolve => {
resolve()
})
.then(() => {
console.log(1)
})
.then(() => {
console.log(2)
})
.then(() => {
console.log(3.1)
})
})
.then(() => {
console.log(1.1)
new Promise((resolve => {
resolve()
}))
.then(() => {
new Promise(resolve => {
resolve()
})
.then(() => {
console.log(4)
})
.then(() => {
console.log(6)
})
}).then(() => {
console.log(5)
})
}).then(() => {
console.log(3)
})
console.log(0)
Output:
0
1
1.1
2
3
3.1
4
5
6
Promises are async. This means everytime you create a new promise- a new async operation starts.
What is async operation in JS? First you need to understand that JS operates on a single thread no matter what you do. So, to make it looks like its asynchronous- there is something called the "event loop" (took the link from comment to original post, tnx #Taki for the great source).
In general, the event loop stores all the async functions and "slips" in the actions between the main code actions. This is really over-simplified explanation, refer to the link to read more, but thats the gist of it.
So basically, there is no "FIFO" queue here- the async functions order is literally depends on stuff like your processor speed, your operating system, etc.
BUT- there is a way to make sure one async action does get performed only after another one finishes, and this is the .then clause. The thing is, it only assures the specific function inside the .then will be performed after the specific promise it was concatenated to, but it does not say anything about the order of it in regars to other async operations (promises) in the event loop. So for example in your code:
new Promise(resolve => {
resolve() // PROMISE A
})
.then(() => {
new Promise(resolve => {
resolve() // PROMISE B
})
.then(() => {
console.log(1) //PROMISE C
})
.then(() => {
console.log(2)
})
.then(() => {
console.log(3.1)
})
})
.then(() => {
console.log(1.1) // PROMISE D
new Promise((resolve => {
resolve()
}))
I took part of it to explain:
so, Promise A resolves first. this assures that promise B will resolve now. here is when things gets complicated: since promise B is resolved, both promise C and D now get into event loop! why? because Promise A had 2 .then clauses, so when the first one ends- event loop takes the 2nd one which is promise D. but the first .then clause had also a .then clause of his own - promise C, which also enters the event loop.
THERE IS NO CONNECTION BETWEEN PROMISE D AND C! They could be performed in any order. keep that logic and you'll see how it works out for the rest of the promises, and also if you try to run it on different OS it might be that promises order will be different because of different implementations of the OS for the event loop.
Hope this helps you to understand a little.
DISCLAIMER: I have not much experience in JS, but promises really intrigued me so I did a deep research about it. I'm standing behind everything I wrote here, but if there are any corrections to my explanation I'd love to hear!
EDIT
The answer beneath me is also correct but with no explanation, so let me add to it:
When you do not return anything inside a promise (or a .then clause, which also returns a promise), it will implicitly return a resolved promise with no value before going out of the promise, basically like adding a return new Promise.resolve() after teh console.log in promise C, for example. When its done like this, all the .then clauses coming after promise B will only enter the event loop after the previous one ended (e.g b ends, so C goes into loop, then the next .then and so on), but between them other promises or .then clauses (like promise D) can enter as well.
But, when you RETURN the promise that has the .then clauses chained to it- it makes sure the whole block of the promise + then clauses goes into event loop as one in order, so the .then clauses will also be performed in the order you wanted :)
tnx #Eugene Sunic for the addition!
It results in unpredictable order because of un-existing returns in your code.
Adding return to your promises and you'll get comprehensible outputs and can easily track the promises execution.
Firstly, synchronous 0 is printed then the entire first promise block gets executed, like you said FIFO.
1,2, 3.1
After that the chaining thenable gets executed
1.1
After that the block 4,6 gets printed
following the chaining thenable which outputs 5 and at last, the last thenable prints number 3
Leaving us with 0,1,2, 3.1, 1.1, 4,6,5,3
new Promise(resolve => resolve())
.then(() => {
return new Promise(resolve => resolve())
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => console.log(3.1));
})
.then(() => {
console.log(1.1);
return new Promise((resolve => resolve()))
.then(() => {
return new Promise((resolve) => resolve())
.then(() => console.log(4))
.then(() => console.log(6))
}).then(() => console.log(5))
}).then(() => console.log(3))
console.log(0)
It's FIFO and the execution looks like this:
main [4] logs: 0 // main code executed, one executor added to FIFO (4)
4 [8,18] // executor at line 4 runs, two executors added to FIFO (8, 18)
8 [18,11] logs: 1 // etc etc
18 [11,23,36] logs: 1.1
11 [23,36,14] logs: 2
23 [36,14,27,33]
36 [14,27,33] logs: 3
14 [27,33] logs: 3.1
27 [33,30] logs: 4
33 [30] logs: 5
30 logs: 6
as you can see its first in first out order: [4,8,18,11,23,36,14,27,33,30] but it stores executors (callbacks for promises that were fulfilled or rejected), not promises. In other words: the time when promise is fulfilled or rejected decides when its added to FIFO not the time the promise is created.
I am trying to wrap my head around promise object in JavaScript. So here I have this little piece of code. I have a promise object and two console.log() on either side of the promise object. I thought it would print
hi
There!
zami
but it printed
hi
zami
There!
Why it is like that? I have zero understanding on how promise works, but I understand how asynchronous callback works in JavaScript. Can any one shed some light on this topic?
console.log('hi');
var myPromise = new Promise(function (resolve, reject) {
if (true) {
resolve('There!');
} else {
reject('Aww, didn\'t work.');
}
});
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
}, function (result) {
// Reject callback.
console.error(result);
});
console.log('zami');
Summary:
A promise in Javascript is an object which represent the eventual completion or failure of an asynchronous operation. Promises represent a proxy for a value which are getting in some point in the future.
A promise can have 3 states which are the following:
Pending: This is the initial state of the promise, the promise is now waiting for either to be resolved or rejected. For example, when are reaching out to the web with an AJAX request and wrapping the request in a promise. Then the promise will be pending in the time window in which the request is not returned.
Fulfilled: When the operation is completed succesfully, the promise is fulfilled. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are succesfully getting data back the promise is said to be fulfilled.
Rejected: When the operation has failed, the promise is rejected. For example, when we are reaching out to be web using AJAX for some JSON data and wrapping it in a promise. When we are getting a 404 error the promise has been rejected.
Promise Constructor:
We can create a promise in the following manner:
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');
Points of interest:
The code inside the promise constructor is synchronously executed.
then method takes as a first argument a callback which is asynchronously executed on promise fulfillment.
then method takes as a second argument a callback which is asynchronously executed on promise rejection. However we are usually using the catch method for this (because this is more verbose), which also takes a callback which is asynchronously executed on promise rejection. catch is essentially the same as then(null, failCallback).
The then callback receives as a first argument the resolved value (the string 'success' in this case).
The catch callback receives as a first argument the rejected value (the string 'Error' in this case).
The finally method receives a callback which is executed on both promise fulfillment and rejection. Here we can write 'cleanup' code which need to be executed always regardless of promise outcome.
Your example:
In your code 'Zami' was printed before 'there' because the log which logged 'there' was in a then callback function. We earlier pointed out that these callbacks are executed asynchronously and thus will be executed last.
Promise execution is asynchronous, which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code.
Basically, your code is doing the following:
Log 'Hi'
Create a promise
Execute the promise
Log 'zami'
Promise is resolved and logs 'There'.
If you want it to print 'Hi there, zami', you will have to
myPromise.then(function (result) {
// Resolve callback.
console.log(result);
console.log('zami');
}, function (result) {
// Reject callback.
console.error(result);
});
Even though you resolved the promised synchronously, the handlers you pass into then get called asynchronously. This is according to the defined specification:
onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack
I would recommend you to understand how event loop works in JavaScript.
take time and watch this Video.
It will clear your doubts.
A Promise is an object representing the eventual completion or failure of an asynchronous operation.
Below is the example of promise:
const post = new Promise((resolve, reject) => {
resolve("Appended from getPostWithPromise()");
});
const getPostWithPromise = function () {
post
.then(function (fulfilled) {
$("body").append("<div>" + fulfilled + "</div>");
})
.catch(function (error) {
console.log(error);
});
}
function getPostWithoutPromise() {
$("body").append("<div>Appended from getPostWithoutPromise()</div>");
}
$(function () {
getPostWithPromise(); // this will print last
getPostWithoutPromise(); // this will print first
$("body").append("<div>Appended directly</div>"); // second
});
you can test it => JavaScript Promises example
for detail understanding you can read this post => https://scotch.io/tutorials/javascript-promises-for-dummies
Promise:
new Promise((resolve, reject) => {
resolve(whateverObject)
reject(whateverErrorObject)
})
It is just object that can be chained with then()
You also can make promise! you can return whatever object in that success parameter (resolve) and error parameter (reject)
so very simple concept bro!
Promises are objects.
Each promise object has a then method.
The then method of the promise object accepts a function as a first parameter.
If we call the then method of a promise, the callback function will be executed once the promise gets resolved.
Flow of execution
const promiseObj = new Promise((res, rej) => {
console.log("Promise constructor are synchronously executed");
res("Hii Developer");
})
const callbackFunction = (resolvedValue) => console.log("Resolved Value ", resolvedValue);
promiseObj.then(callbackFunction);
console.log("I am the executed after the constructor");
In the above example, we have created a promise object using the Promise constructor.
The constructor function is synchronously executed.
After creating the promise object, we are calling the then method of the promise object. We have passed a callback function in the first argument of the then method. This callback function will be executed once the promise gets resolved and the stack of the js engine gets empty.
Promise is a object that represents the completion or failure of a event . Promise is a asynchronous thing in JS which means that it's executed, but the program won't wait until it's finished to continue with the rest of the code. So it wont be executed simultaneously. It would take time to either complete or fail for a given task and then execution.
In your Case
log'Hi'.
First your mypromise variable will store a promise object i.e either rejected or resolved(for this, it would take time)
But JS engine will execute further code first then the asynchronous task. SO u will get 'zami'.
once the promise resolved or rejected. It will be called or used wherever it is used in the code. In this case ,it is resolved and log 'there!' in console.
let prom = new Promise((res, rej) => {
console.log('synchronously executed');
if (Math.random() > 0.5) {
res('Success');
} else {
rej('Error');
}
})
prom.then((val) => {
console.log('asynchronously executed: ' + val);
}).catch((err) => {
console.log('asynchronously executed: ' + err);
}).finally(() => {
console.log('promise done executing');
});
console.log('last log');