A is an object consisting of state, result, callback handler
When the status is changed to success/ failed, the callback function will be put into micro-task queue
Why need promise?
As we know, javascript is single-thread. If async function is arranged, the callback will be done at the end of the function, which is not the same as our expectation. Therefore, we need promise to queue up the handler. For example: For the api call, we might want trigger the handler in sequence after the data is got from api end point.
Case 1 :
const test = () => {
console.log('Program Start');
setTimeout(() => { console.log('async Function');}, 0);
console.log('End');
}
test();
// Expectation:
// Program Start
// async Function
// End
// Output:
// Program
// End
// async Function
Ajax method is also a typical example. Let's take axios as an example
Case 2:
const test = () => {
let data = {};
data = axios.get(url ,{});
console.log('Data:',data);
}
test();
// Expectation:
// data: real data
// Output:
// data: {}
Status of Promise
Pending: the promise function is progressing
Fulfilled: the promise function is successful
Rejected: the promise function is failed
Structure of Promise
Then : Promise return successfully
Catch : Failed to return promise, to do error handling
Final : The end of the promise function
Example:
const promise = () => {
return new Promise((resolve,reject) => {
// get 0 or 1 randomly
const num = Math.random() > 0.5 ? 1 : 0;
if (num) {
// declare the return value when fulfilled
resolve('success ya!');
}
else{
// declare the return value when rejected
reject('failed');
}
})
}
const test = () => {
promise().then((value)=>
{
console.log(value); // success ya!
}).catch((error)=>{
//to do error handling
console.log(error); // failed
}).final(()=>{
console.log("finished"); // finished
})
}
test();
// Output:
// successya!!! / failed
// finished
Rewrite by using promise
Case 1:
const timeout = () => {
return new Promise((resolve, reject)=>{
setTimeout(() => {
console.log('async Function');
resolve("success");
}, 0);
})
}
const test = () => {
timeout.then((value)=>{
console.log('End');
console.log(value);
})
}
test();
// Output:
// async Function
// End
Case 2: (Actually axios is a function with promise, so we don't need to make a new promise function)
const test = () => {
let data = {};
axiox.get(url,{}).then((data)=>{
data = success;
console.log('data:',data);
})
}
// Output:
// data: real data
Feature
Callback
The resolve and reject is a callback of the promise, so that it will be triggered at last
Compare and return the promise that is the fastest to be resolved
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
// Expected output: "two"
Async & Await
Introduction
With long chaining of promise, which may make the code not readable
const listOfIngredients = [];
doSomething()
.then((url) => {
// `return` keyword now included in front of fetch call.
return fetch(url)
.then((res) => res.json())
.then((data) => {
listOfIngredients.push(data);
});
})
.then(() => {
console.log(listOfIngredients);
// listOfIngredients will now contain data from fetch call.
});
In order to make code more clean and looks exactly like synchronous code, we can use async await to replace the chaining
async function logIngredients() {
const url = await doSomething();
const res = await fetch(url);
const data = await res.json();
listOfIngredients.push(data);
console.log(listOfIngredients);
}
Return Value
The return value must be a promise
In sequence vs Concurrent
const testAsync = async(input) => {
const data = await Promise.resolve(input);
console.log(data);
}
const inSequence = async() => {
const array = [1,2,3];
for(const i of array){
await testAsync(i);
}
}
const concurrent = async()=>{
await Promise.all([1,2,3].map((i)=>testAsync(i)));
}
// avoid using foreach for promise due to unexpected behaviors
// ref: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404