A promise object is created from Promise constructor/class which needs a callback function AKA executor function .
This callback function receives the resolve and reject function arguments, either of which we must envoke with an optional payload.
When resolve is called,then method (AKA handler) is called which executes successCallback with successPayload while if reject is called,catch handler is called which executes errorCallback with errorPayload. finally handler is always called (without any payload) when the promise is settled, which means either resolve or reject is called.finally is called before then or catch handler if it appears first i.e, before then or catch handler.
Attention:
1. catch handler will be invoked by the promise not only when we reject the promise but even when JavaScript encounter runtime error in the executor function of the promise.
In the above example, we are trying to increment a variable which does not exist. Since this error was thrown in the executor function, Promise catches it and calls then catch handler with the error payload. If the runtime error occurs in the callback function of an async call (inside the executor function), then the error will won’t be caught, as shown below.
2. The then handler takes the second argument which should be a function to handle the promise rejection.But it is standard practice to use the catch method handler to handle promise rejection instead of using then method. If you use both catch and then method to handle promise rejection, catch handler will be ignored.
Priority: 宏任务同步-> 微任务(microtask queue, such as Promise) -> 宏任务异步(macrotask queue, such as setTimeOut, setInterval, setImmediate)
From the above example, all synchronous console.log statements got executed first because they were pushed on thestackfirst. Then we had callback of setTimeout waiting on the macrotask queue while the callback of promiseA was waiting on the microtask queue and event loop chosemicrotaskto be executed first and then amacrotask.
Promise.resolve( data ) and Promise.reject( errData )
The resolve and the reject are the static methods of Promise class which returns a promise object and immediately fulfils and rejects it respectively. For example, Promise.resolve() method looks similar to below.
const fulfilledPromise = new Promise( ( resolve ) => resolve() )
But an important thing to remember about promises is that even when we are calling resolve or reject immediately, i.e., without an async function, its callback handlers will be called only when the main JavaScript execution has done all pending work. That means, once the stack is empty, our promise handlers will get executed.
Different states of a promise
As we know that a promise will be fulfilled when resolve is called from within the executor function and then it invokes then handler. Until then, a promise is in the pending state, which means it is yet to be settled. Once resolve is called, it acquires fulfilled state or when reject is called, it acquires rejected state. Promise does not provide any API to check the current state of a promise but you can use debugger tool to convince yourself.
Promise handler returns a new promise
We have seen then, catch and finally methods which are prototype methods of Promise class. These methods are chainable, which means we can call them on each other. This is possible because all these methods return a new promise.
If the promise is fulfilled, then returns a new fulfilled promise with undefined payload (data). If there is a return statement in the handler function, it returns a fulfilled promise with that return value as the payload.
If the promise is rejected, catch returns a new promise with undefined payload (data). If there is a return statement in the handler function, it returns a fulfilled promise with that return value as the payload.
finally returns a new promise with undefined payload (data). If there is a return statement in the handler function, it returns a fulfilled promise with that return value as the payload.
Only first then is invoked when the promise is fulfilled and only first catch is invoked when the promise is rejected. After that, depending on the appearance of then and catch handlers, the handler function will be called. Let’s see an example of this in details.
Promise.all() and Promise.race()
Promise.all([promises]) method takes an array of promises and returns a new promise. This promise will be fulfilled when and if all promises are fulfilled. Promise.race([promises]) also takes an array of promises and returns a new promise which fulfils if any of the promises fulfils.
In the case of both these method, if any of the promises is rejected early, promise returned by these methods will be rejected and the results of other promises will be ignored. In the case of race method, as promises are racing with each other, if one of the given promises fulfils early, returned promise will be fulfilled immediately with the value of the fulfilled promise.
We can also pass non-promise objects inside an array. They will act like a fulfilled promise created using Promise.resolve() function.
Async/Await
Async/Await is a fancier syntax to handle multiple promises in synchronous code fashion. When we put async keyword before a function declaration, it becomes a promise and we can use await keyword inside it which blocks the code until promise it awaits resolves or rejects.
If any of the promises is rejected inside an async function, the promise it returns will reject as well with the error message. The returned promise is also rejected if any runtime error occurs inside the async function (similar behaviour to a promise which rejects when a runtime error occurs in Promise constructors executor function).
The word “async” before a function means one simple thing: a function always returns a promise. If the code has return <non-promise> in it, then JavaScript automatically wraps it into a resolved promise with that value.
The keyword await makes JavaScript wait until that promise settles and returns its result.That doesn’t cost any CPU resources, because the engine can do other jobs meanwhile: execute other scripts, handle events etc.It’s just a more elegant syntax of getting the promise result than promise.then, easier to read and write.
As said, await only works inside async function. Like promise.then, await allows to use thenable objects (those with a callable then method). Again, the idea is that a 3rd-party object may not be a promise, but promise-compatible: if it supports .then, that’s enough to use with await.
For instance, here await accepts new Thenable(1):
If a promise resolves normally, then await promise returns the result. But in case of a rejection, it throws the error, just as if there were a throw statement at that line.
Is async/await blocks the main thread
From await syntax keyword looks like that it blocks the execution of the thread until the promise it is awaiting on resolves. But that’s is not the case. The while async/await pattern is still based on classical Promise syntax.
Async function is more like your promise executor function which runs synchronously. The await keyword is like a then callback that wraps all the statements below it.
refer:
https://itnext.io/javascript-promises-and-async-await-as-fast-as-possible-d7c8c8ff0abc