-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
This proposal allows the Typescript language service to automatically refactor code that uses Promise methods such as .then()
or .catch()
to instead use the async
and await
keywords.
Async/await offers many advantages over promise methods including cleaner syntax, error handling, debugging, and readability. The benefits of the synchronous style code provided by async/await are largely recognized by the Javascript community. However, there is still a substantial amount of asynchronous code written using Promises. This proposal will provide a quick and simple transition to using the async/await keywords.
Simple Examples
Input:
function ex1(): Promise<boolean> {
return fetch('https://microsoft.com').then( result => result.ok; );
}
Output:
async function ex1(): Promise<boolean> {
let result = await fetch('https://microsoft.com');
return result.ok;
}
onRejected handlers:
Input:
function ex2(): Promise<void> {
return fetch('https://microsoft.com').then( result => console.log(result), rej => console.log("error", rej) );
}
Output:
async function ex2(): Promise<void> {
let result;
try {
result = await fetch('https://microsoft.com');
}
catch (rej) {
return console.log("error:", rej);
}
return result.ok;
}
Note that this conversion does not preserve semantics. In order to create clean, readable code, the semantics of some code is slightly altered.
Catch handlers:
Input:
function ex3():Promise<void> {
return fetch('https://microsoft.com').then(result => console.log(result)).catch(err => console.log(err));
}
Output:
async function ex3():Promise<void> {
let result;
try {
result = await fetch('https://microsoft.com');
await console.log(result);
}
catch (err) {
await console.log(err);
}
}
More Examples - multiple handlers
Multiple .then() calls:
In situations where variable names intersect, a new variable name will be chosen for intermediate variables. For example:
Input:
function ex4():Promise<boolean> {
return fetch('https://microsoft.com').then(res).then(res2);
}
function res(result){
return result.ok;
}
function res2(result){
console.log(result);
}
Output:
async function ex4():Promise<boolean> {
let result = await fetch('https://microsoft.com');
let temp = await res(result);
return res2(temp);
}
function res(result){
return result.ok;
}
function res2(result){
console.log(result);
}
Multiple .catch() calls
Input:
function ex5(): Promise<void> {
return fetch('https://microsoft.com').then(res => console.log(res)).catch(err => console.log("err")).catch(err2 => console.log("err2", err2));
}
Output:
async function ex5(): Promise<void> {
try {
let res;
try {
res = await fetch("https://microsoft.com");
return console.log(res);
}
catch (err) {
return console.log("err");
}
}
catch (err2) {
return console.log("err2");
}
}
More Examples - Promise.all() and Promise.race()
In order to preserve semantics, code that uses Promise.all()
cannot be entirely refactored.
Input
function ex6():Promise<void> {
return Promise.all([fetch('https://microsoft.com'), fetch('https://microsoft.com'), fetch('https://youtube.com')]).then(
function(vals){
vals.forEach(console.log);
});
}
Output:
async function ex6():Promise<void> {
let vals = await Promise.all([fetch('https://microsoft.com'), fetch('https://microsoft.com'), fetch('https://youtube.com')]);
return vals.forEach(console.log);
}
Similarly, code that uses 'Promise.race()' is partially refactored:
Input
function ex7():Promise<void> {
return Promise.race([fetch('https://microsoft.com'), fetch('https://microsoft.com'), fetch('https://youtube.com')]).then(val => console.log(val));
}
Output:
async function ex7():Promise<void> {
let val = await Promise.race([fetch('https://microsoft.com'), fetch('https://microsoft.com'), fetch('https://youtube.com')]);
return console.log(val);
}
More Examples - Returning variables of Promise type
In order to preserve semantics, a refactoring will only be offered for functions that directly return a promise with callbacks.
For example, a refactoring will not be offered for the following:
function ex8() {
let blob = fetch("https://typescriptlang.org").then(resp => console.log(resp));
return blob;
}
However, a refactoring will be offered for the following function as it can be converted to use async and await while preserving semantics:
function ex9() {
return fetch("https://typescriptlang.org").then(resp => console.log(resp));
}
Support for .finally()
will be coming later