co.js - 讓異步代碼同步化

近期在全力開發我的網站,而且又沉澱了一些先後端的技術。近期會頻繁更新。javascript

這篇文章首發於個人我的網站:據說 - https://tasaid.com,建議在個人我的網站閱讀,擁有更好的閱讀體驗。html

這篇文章與 博客園 和 Segmentfault 共享。前端

前端開發QQ羣:377786580java

coTJ 大神所編寫的 JavaScript 異步解決方案的庫,用於讓異步的代碼 "同步化"。git

它構建在如下兩個基礎上,這篇文章不會詳細講解這 2 個知識點:github

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 關鍵字暫停函數,並返回當前函數的狀態。ide

co 實現了 generator自動執行,咱們使用 coPromise 修改上面的代碼:

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

參考和引用

相關文章
相關標籤/搜索