近期在全力開發個人網站,並且又沉淀了一些前后端的技術。近期會頻繁更新。
這篇文章首發於我的個人網站:聽說 - https://tasaid.com/,建議在我的個人網站閱讀,擁有更好的閱讀體驗。
這篇文章與 博客園 和 Segmentfault 共享。
前端開發QQ群:377786580
co 是 TJ 大神所編寫的 JavaScript 異步解決方案的庫,用於讓異步的代碼 "同步化"。
它構建在以下兩個基礎上,這篇文章不會詳細講解這 2 個知識點:
Generator 和 co
首先我們簡單了解下 generator
:
// 定義一個 generators
function* foo(){
yield console.log("bar");
yield console.log("baz");
}
var g = foo();
g.next(); // prints "bar"
g.next(); // prints "baz"
簡單來說,generator
實現了狀態暫停/函數暫停 —— 通過 yield
關鍵字暫停函數,並返回當前函數的狀態。
co
實現了 generator
的 自動執行,我們使用 co
和 Promise
修改上面的代碼:
var co = require('co');
function* foo() {
yield Promise.resolve(console.log("bar"));
yield Promise.resolve(console.log("baz"));
}
var co = require('co');
co(foo);
有人可能要說 "我自己寫個循環執行 next 不也可以么? 為什么一個循環還要依賴一個庫?"
co
有個使用條件:generator
函數的 yield
命令后面,只能是 Thunk 函數或 Promise
對象。
正是這個條件,讓 co
強悍無比。
Callback
我們一步一步來看異步,首先使用 回調函數/Callback
的方式封裝一個常見的 ajax
異步任務:
function ajax(q, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
callback(xhr.responseText);
}
}
xhr.open("GET", "query?q=" + q);
}
我們使用 回調函數
的方式連續發 2 條請求:
ajax('foo', function (foo) {
console.log(foo);
ajax('bar', function (bar) {
console.log(bar);
});
});
這是 js 中最典型的異步處理方案。
Promise
再使用 Promise 封裝異步 ajax,讓回調函數扁平化:
function ajax(q, callback) {
// 使用 Promise 封裝
return new Promise(function (resolve) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
}
xhr.open("GET", "query?q=" + q);
});
}
然后修改請求代碼,扁平化異步代碼:
ajax('foo')
.then(function (foo) {
console.log(foo);
return ajax('bar')
})
.then(function (bar) {
console.log(bar);
});
co
最后,讓我們見一下 co
的強悍之處吧。我們使用 co.js
來修改請求代碼:
var co = require('co');
co(function* () {
var foo = yield ajax('foo');
console.log(foo);
var bar = yield ajax('bar');
console.log(bar);
});
最終我們的異步任務,在代碼中同步化了。
對於異步代碼來說,回調函數是最基礎的方案,帶來的弊端也顯而易見。Promise
讓代碼扁平化,而 co
讓代碼同步化。
這篇文章首發於我的個人網站:聽說 - https://tasaid.com/,建議在我的個人網站閱讀,擁有更好的閱讀體驗。
這篇文章與 博客園 和 Segmentfault 共享。
前端開發QQ群:377786580