Async & Await
This document is a quick introduction to using the async
and await
syntactic sugar in CloudCode tasks and in TypeScript apps.
Start with this interactive introduction to async
& await
if you are not familiar with the syntax at all.
Introduction to async and await usage
In JourneyApps many operations are asynchronous. We use async
& await
to handle this.
In CloudCode, your main run
function should always be async
:
export async function run() {
// Code here
}
Generally, database operations that query the backend are asynchronous, and needs await
:
export async function run() {
var user = await DB.user.first();
console.log('name:', user.name);
// This doesn't hit the database yet, so does not need `await`
var assignment = DB.assignment.create();
assignment.user(user);
await assignment.save();
}
Fetch calls are also asynchronous and therefore require an await
:
export async function run() {
var response = await fetch("http://api.open-notify.org/iss-now.json");
if(!response.ok) {
throw new Error('Request failed: ' + response.statusText);
}
var body = await response.json();
return body.iss_position;
}
If you define an async
function, you also need to await
on its response:
async function getLocation() {
var response = await fetch("http://api.open-notify.org/iss-now.json");
if(!response.ok) {
throw new Error('Request failed: ' + response.statusText);
}
var body = await response.json();
return body.iss_position;
}
export async function run() {
var location = await getLocation();
return {location: location};
}
Notable async
operations:
someModel.first()
someQuery.toArray()
someQuery.first()
someQuery.destroyAll()
someQuery.count()
someDbObject.save()
someDbObject.destroy()
someDbObject.reload()
Getting belongs-to
relationships are also async
. If a chain of belongs-to
lookups are performed, each one requires an await
. For readable code, it is recommended to do each belongs-to
lookup on a separate line. For example:
// Works, but not readable
let clientName = (await (await user.assignment()).client()).name;
// More readable
let assignment = await user.assignment();
let client = await assignment.client();
let clientName = client.name;
for
loops require specific attention: someArray.forEach
does not wait for async
functions to complete, so it is recommend to use a for...of
loop instead:
var objects = await DB.myobject.all().toArray();
for(let object of objects) {
// ...
}
For example:
export async function run() {
// Task to recalculate the totals for all invoices
var invoices = await DB.invoices.all().toArray();
for(let invoice of invoices) {
var line_items = await invoice.line_items.toArray();
var total = 0;
for(let line_item of line_items) {
var product = await line_item.product();
var price = product.price * line_item.quantity;
total += price;
}
invoice.total = total;
await invoice.save();
}
}
Last updated