Careeroza
Promises and async await
Promise of T
An async function always returns a Promise<T>, where T is the type of the value you return. await unwraps it back to T.
Example
type Product = { id: number; name: string; price: number };
const delay = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
async function getProduct(id: number): Promise<Product> {
await delay(20); // pretend this is a database call
return { id, name: "Product " + id, price: id * 100 };
}
async function main() {
console.log("loading...");
const p = await getProduct(7); // Product, not Promise<Product>
console.log(p.name, p.price);
const pending = getProduct(8); // Promise<Product>
pending.then((x) => console.log("then:", x.name));
}
main();Output
loading... Product 7 700 then: Product 8
Forgetting await
Example
Without await you have a Promise, not the price (TS2339: toFixed does not exist on Promise<number>).
async function getPrice(): Promise<number> {
return 499;
}
async function main() {
const price = getPrice();
console.log(price.toFixed(2));
}
main();Compiler output (tsc)
Line 7: error TS2339: Property 'toFixed' does not exist on type 'Promise<number>'.
Creating a Typed Promise
Example
new Promise<T> types the resolve callback. Here a callback-style function is converted to a promise.
function legacyLookup(pin: string, cb: (err: Error | null, city?: string) => void): void {
setTimeout(() => (pin === "500081" ? cb(null, "Hyderabad") : cb(new Error("Unknown PIN"))), 10);
}
function lookup(pin: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
legacyLookup(pin, (err, city) => (err ? reject(err) : resolve(city ?? "")));
});
}
async function main() {
console.log(await lookup("500081"));
try {
await lookup("000000");
} catch (e) {
console.log("Failed:", (e as Error).message);
}
}
main();Output
Hyderabad Failed: Unknown PIN