// ...
const res = await fetch(endpointUrl);
const data = await res.json();
// ...do whatever with the data...
Using Promises:
// ...
fetch(endpointUrl)
.then(res => res.json())
.then(data => {
// ...do whatever with the data...
})
async () => {
const res = await fetch(endpointUrl);
const data = await res.json();
// ...do whatever with the data...
}
Must have this
async function() {
const res = await fetch(endpointUrl);
const data = await res.json();
// ...do whatever with the data...
}
async () => {
try {
const res = await fetch(endpointUrl);
if (res.ok) {
const data = await res.json();
console.log("Final result:", data);
} else {
throw Error(res.statusText);
}
} catch (err) {
console.error("Fetch failed:", err);
}
}
Reads just like normal code (no .catch())
An async function returns a promise automatically
async () => {
try {
const res = await myAsyncFunc();
// do stuff...
} catch (e) {
// act on error...
}
}
Or
myAsyncFunc()
.then(res => // do stuff...)
.catch(err => // act on error...)
`await` can only be used in an `async` context. Don't do this:
const aNonAsyncFunc = () => {
try {
const res = await myAsyncFunc();
// do stuff...
} catch (e) {
// act on error...
}
}
Syntax Error
class MyComp extends React.Component {
state = { dataItems: [] };
componentDidMount() {
(async () => {
const data = await fetch("endpoint.url");
const dataItems = await data.json();
this.setState({ dataItems });
})();
}
render() {
const { dataItems } = this.state;
return dataItems.length > 0 ? (
<ul>{dataItems.map(item => <li>{item.name}</li>)}</ul>
) : (
"Loading..."
);
}
}
IFE
In a front-end application:
const main = async () => {
// Your main process code here
};
main();
In the global scope:
Main Thread
asyncFunc()
const asyncFunc = async () => {
const resA = await fetch(urlA);
const dataA = await resA.json();
// ...do stuff
const resB = await fetch(urlB);
const dataB = await resB.json();
// ...do more stuff
return [...dataA, ...dataB];
}
Function Execution
Halt
Halt
.then() or await
always running, never blocked
Halt
Halt
const response = await fetch("https://api...");
const json = await response.json();
console.log(json);
fetch("https://api...")
.then(response => {
return response.json();
})
.then(json => {
console.log(json);
});
const get = async (url) => {
const response = await fetch(url);
return response.json();
}
const getDatas = async () => {
// Fire off both requests at the same time
const dataA = get("endpoint/a");
const dataB = get("endpoint/b");
// Return once both have resolved
return { dataA: await dataA, dataB: await dataB};
}
const names = [];
fetches.forEach(async (fetchInProcess) => {
const res = await fetchInProcess;
const data = await res.json();
console.log(data.name);
names.push(data.name);
});
console.log("==FINISHED==");
console.log(names);
// ** Evaluates to: **
//
// "==FINISHED=="
// []
// "Darth Vader"
// "Leia Organa"
// "R2-D2"
// "C-3PO"
// "Luke Skywalker"
Main Thread
= async actions
(always running, never blocked)
A sequence of async actions can be executed one at a time, in order, waiting to start the next until the previous is finished
async (items) => {
for (item of items) {
const result = await db.get(items[i]);
console.log(result);
}
}
async (items) => {
const promises = items.map(
item => db.get(item)
);
const results = await Promise.all(promises);
console.log(results);
}
Main Thread
= async actions
(always running, never blocked)
1
2
3
4
1
2
3
4
{
Execute all actions at once
async (items) => {
// Kick off the async actions
const promises = items.map(
item => db.get(item)
);
for (promise of promises) {
const data = await promise;
console.log(data);
}
}
The Flow:
Main Thread
= async actions
(always running, never blocked)
A sequence of async actions can be executed one at a time, in order, waiting to start the next until the previous is finished
const story = {
title: "The Book of Mormon",
chapterUrls: ["my.endpoint/1", "my.endpoint/2", "my.endpoint/3"]
};
// Start off with a promise that always resolves
let sequence = Promise.resolve();
// Loop through our chapter urls
story.chapterUrls.forEach((chapterUrl) => {
// Add these actions to the end of the sequence
sequence = sequence
.then(() => getJSON(chapterUrl))
.then(chapter => addHtmlToPage(chapter.html))
})
The Code: (using a for loop)
const story = {
title: "The Book of Mormon",
chapterUrls: ["my.endpoint/1", "my.endpoint/2", "my.endpoint/3"]
};
// Loop through our chapter urls
story.chapterUrls.reduce((sequence, chapterUrl) => {
// Add these actions to the end of the sequence
return sequence
.then(() => getJSON(chapterUrl))
.then(chapter => addHtmlToPage(chapter.html));
}, Promise.resolve());
The Code: (using Array.prototype.reduce())
The Flow:
Main Thread
= async actions
(always running, never blocked)
1
2
3
4
1
2
3
4
{
Execute all actions at once
const story = {
title: "The Book of Mormon",
chapterUrls: ["my.endpoint/1", "my.endpoint/2", "my.endpoint/3"]
};
story.chapterUrls.map(getJSON) // <-- Fire off all the async actions
.reduce((sequence, chapterPromise) => {
// Then use reduce to chain the promises together,
// adding content to the page for each chapter
return sequence
.then(() => {
// Wait for everything in the sequence so far,
// then wait for this chapter to arrive.
return chapterPromise;
})
.then(chapter => addHtmlToPage(chapter.html));
}, Promise.resolve());
Note: This method will be replaced by `for await of`
babel-plugin-transform-async-to-generator
babel-plugin-transform-runtime
babel-preset-env
ππ₯
npm install --registry="http://icsnpm.ldschurch.org" -g ldsjs
ldsjs react your-sweet-app-name
Use the ICS Stack Team v3.x React starter
async/await is ready out of the box!
const someThing = require('some-thing')
someThingWrapper = () =>
new Promise(resolve => {
someThing((err, result) => {
if (err) {
reject(err)
}
resolve(result)
})
})
const main = async () => {
try {
const result = await someThingWrapper()
// do stuff with result
} catch (err) {
console.error(err)
}
}
main()