【TypeScript】如何在TypeScript中使用async/await,讓你的代碼更像C#。
async/await
提到這個東西,大家應該都很熟悉。最出名的可能就是C#中的,但也有其它語言也實現。比如,Python 3.5中、比如Js中的yield/generator。
Typescript 當前版本1.8.x,1.7版本開始支持async/await, 當然只支持es6編譯。2.1版本說是將支持到es5/es3.
Typescript Roadmap : https://github.com/Microsoft/TypeScript/wiki/Roadmap
優點
在這種方式之前,我們主要用的方式,就是回調方式。但如果,你的當前這個調用依賴於回調的數據,當這種關係依賴的多些時候,想想你的代碼。
有了 async/await的方式,可以讓異步的調用,用起來像同步一樣。
場景
想一下這樣的場景,有三個http請求,每一個都要依賴上一個請求的返回結果。
我們用js在node中,模擬一下這樣的場景。
let http = require('http');
function test() {
http.get('http://www.baidu.com', function (res) {
console.log('the first Status :' + res.statusCode);
http.get('http://www.163.com', function (res2) {
console.log('the second Status :' + res2.statusCode);
http.get('http://www.sina.com', function (res3) {
console.log('the third Status :' + res3.statusCode);
})
})
});
}
test();
我們再來看一下 Typescript 中,用 async/await 的方式。
import http = require('http');
class httpAsync {
constructor() {
}
public async GetAsync(url: string): Promise<http.IncomingMessage> {
var promise = new Promise<http.IncomingMessage>(resolve => {
http.get(url, res => {
resolve(res);
});
});
return promise;
}
}
async function test() {
let ha = new httpAsync();
let res = await ha.GetAsync("http://www.baidu.com");
console.log('the first Status :' + res.statusCode);
res = await ha.GetAsync("http://www.163.com");
console.log('the first Status :' + res.statusCode);
res = await ha.GetAsync("http://www.sina.com");
console.log('the first Status :' + res.statusCode);
}
test();
我們封裝了一個httpAsync類,用async方式包裝了一下,
對比一個 兩個test方法內容,你覺得哪種方式更舒服一些。
如何實現
對C#熟悉的同學,可能很好的理解,因爲Promise很像C#中的TaskCompletionSource<T>.
我們來一段 C# 模擬實現這個功能的, C#中的HttpClient本身是支持async/await模式的,大家不要糾結這個,這裏只是模擬這個方式 .
public class HttpAsync
{
public Task<HttpResponseMessage> GetAsync(string url)
{
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
HttpClient hc = new HttpClient();
hc.GetAsync(url).ContinueWith(res =>
{
tcs.SetResult(res.Result);
hc.Dispose();
});
return tcs.Task;
}
}
對 C# 這方面感興趣的同學,可以去查查,網上的資料很多。
Typescript 實現這種方式,主要是一個關鍵字 async 和一個對象 Promise<T> .
import http = require('http');
class httpAsync {
constructor() {
}
public async GetAsync(url: string): Promise<http.IncomingMessage> {
var promise = new Promise<http.IncomingMessage>(resolve => {
http.get(url, res => {
resolve(res);
});
});
return promise;
}
}
- 方法必須用 async 來標記。
- 可以被 await 的方法必須有返回值 Promise<T> ,如果你的返回值是 void ,那麼方法的返回值就是 Promise<void> .
- 用 Promise<T> 包裝你的調用,當成功時調用__resolve__ 回調 結果 或 Promise<T> ,來確定你的異步完成。
- 可以在 Promise 構造中,再追加一個 reject 參數,來返回執行過程中的原因或錯誤。
- Typescript 最終也會把 async/await 的方式編譯成 js 中類似 yield/generator 的方式
總結
看看 C# 和 Typescript 的代碼,看起來很還是很像的吧。因爲他們的老爹都是一個人, C# 之父也是 Typescript 他爹。
在C#中,我們可能已很熟悉這種方式了,但是在 js/ts 中,我們使用的還不多,而且它也不像C#中提供全面的支持庫,使用的時候,可能還是得酌情處理。