asynchronous programming
Promise
A Promise
is an object representing the eventual completion or failure of an asynchronous operation.
e.g., fetch()
returns a Promise
.
It is always in one of these states: pending, fufilled, rejected.
Use then()
to add callbacks to fufilled
promises, and catch()
for rejected
promises.
Some guarantees:
- Callbacks added with
then()/catch()
will never be invoked before the completion of the current run of the JavaScript event loop - These callbacks will be invoked even if they were added after the success or failure of the asynchronous operation that the promise represents.
- (Chaining) Multiple callbacks may be added by calling
then()
several times. They will be invoked one after another, in the order in which they were inserted.
Chaining:
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {console.log(`Got the final result: ${finalResult}`);})
.catch(failureCallback);
doAnotherthing(); // this will not wait until doSomething() finish !
Catching errors:
new Promise((resolve, reject) => {
console.log('Initial');
resolve();
})
.then(() => {
throw new Error('Something failed');
console.log('Do this');
})
.catch(() => {
console.error('Do that');
})
.then(() => {
console.log('Do this, no matter what happened before');
});
Create promises manually
let p = new Promise((resolveFunc[, rejectFunc]) => {
// do something
// if you returned something, it will be passed to `then`.
});
p.then(handleResolveFunc[, handleRejectFunc]);
Promise.resolve([value]) // returns a dummy resolved Promise with value.
examples:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(10*1000).then(() => console.log("10 seconds later"));
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(0).then(() => console.log(4)); // need to resolve (even 0 ms), second in task queue.
Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); // already resolved promise, first in task queue
console.log(1); // not in task queue
// 1, 2, 3, 4
async / await
async
can be put in front of a function to make it async, i.e., return a Promise.
async function hello() { return "Hello" };
hello(); // return a Promise
hello().then((value) => console.log(value)); // output Hello.
hello().then(console.log) // shorter ver.
await
can be put in front of a Promise
to pause program until it fulfills.
async function hello() {
return greeting = await Promise.resolve("Hello");
};
hello().then(alert);
They can be used to replace then()
chains:
// then ver.
fetch('coffee.jpg')
.then(response => {
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`);}
return response.blob();
})
.then(myBlob => {
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
})
.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message);
});
// async ver.
async function myFetch() {
let response = await fetch('coffee.jpg');
if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}
let myBlob = await response.blob();
let objectURL = URL.createObjectURL(myBlob);
let image = document.createElement('img');
image.src = objectURL;
document.body.appendChild(image);
}
myFetch()
.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message);
});