• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    深入解析koa之異步回調處理

    來源:懂視網 責編:小采 時間:2020-11-27 21:54:59
    文檔

    深入解析koa之異步回調處理

    深入解析koa之異步回調處理:1. 回調金字塔及理想中的解決方案 我們都知道javascript是一門單線程異步非阻塞語言。異步非阻塞當然是它的一個優點,但大量的異步操作必然涉及大量的回調函數,特別是當異步嵌套的時候,就會出現回調金字塔的問題,使得代碼的可讀性非常差。比如下面一個例
    推薦度:
    導讀深入解析koa之異步回調處理:1. 回調金字塔及理想中的解決方案 我們都知道javascript是一門單線程異步非阻塞語言。異步非阻塞當然是它的一個優點,但大量的異步操作必然涉及大量的回調函數,特別是當異步嵌套的時候,就會出現回調金字塔的問題,使得代碼的可讀性非常差。比如下面一個例

    1. 回調金字塔及理想中的解決方案

    我們都知道javascript是一門單線程異步非阻塞語言。異步非阻塞當然是它的一個優點,但大量的異步操作必然涉及大量的回調函數,特別是當異步嵌套的時候,就會出現回調金字塔的問題,使得代碼的可讀性非常差。比如下面一個例子:

    var fs = require('fs');
    fs.readFile('./file1', function(err, data) {
    console.log(data.toString());
    fs.readFile('./file2', function(err, data) {
    console.log(data.toString());
    })
    })

    這個例子是先后讀取兩個文件內容并打印,其中file2的讀取必須在file1讀取結束之后再進行,因此其操作必須要在file1讀取的回調函數中執行。這是一個典型的回調嵌套,并且只有兩層而已,在實際編程中,我們可能會遇到更多層的嵌套,這樣的代碼寫法無疑是不夠優雅的。

    在我們想象中,比較優雅的一種寫法應該是看似同步實則異步的寫法,類似下面這樣:

    var data;
    data = readFile('./file1');
    //下面的代碼是第一個readFile執行完畢之后的回調部分
    console.log(data.toString());
    //下面的代碼是第二個readFile的回調
    data = readFile('./file2');
    console.log(data.toString());

    這樣的寫法,就完全避免回調地獄。事實上,koa就讓我們可以使用這樣的寫法來寫異步回調函數:

    var koa = require('koa');
    var app = koa();
    var request=require('some module');
    app.use(function*() {
    var data = yield request('http://www.baidu.com');
    //以下是異步回調部分
    this.body = data.toString();
    })
    app.listen(3000);

    那么,究竟是什么讓koa有這么神奇的魔力呢?

    2. generator配合promise實現異步回調同步寫法

    關鍵的一點,其實前一篇也提到了,就是generator具有類似"打斷點"這樣的效果。當遇到yield的時候,就會暫停,將控制權交給yield后面的函數,當下次返回的時候,再繼續執行。

    而在上面的那個koa例子中,yield后面的可不是任何對象都可以哦!必須是特定類型。在co函數中,可以支持promise, thunk函數等。

    今天的文章中,我們就以promise為例來進行分析,看看如何使用generator和promise配合,實現異步同步化。

    依舊以第一個讀取文件例子來分析。首先,我們需要將讀文件的函數進行改造,將其封裝成為一個promise對象:

    var fs = require('fs');
    var readFile = function(fileName) {
    return new Promise(function(resolve, reject) {
    fs.readFile(fileName, function(err, data) {
    if (err) {
    reject(err);
    } else {
    resolve(data);
    }
    })
    })
    }
    //下面是readFile使用的示例
    var tmp = readFile('./file1');
    tmp.then(function(data) {
    console.log(data.toString());
    })

    關于promise的使用,如果不熟悉的可以去看看es6中的語法。(近期我也會寫一篇文章來教大家如何用es5的語法來自己實現一個具備基本功能的promise對象,敬請期待呦^_^)

    簡單來講,promise可以實現將回調函數通過 promise.then(callback)的形式來寫。但是我們的目標是配合generator,真正實現如絲般順滑的同步化寫法,如何配合呢,看這段代碼:

    var fs = require('fs');
    var readFile = function(fileName) {
    return new Promise(function(resolve, reject) {
    fs.readFile(fileName, function(err, data) {
    if (err) {
    reject(err);
    } else {
    resolve(data);
    }
    })
    })
    }
    //將讀文件的過程放在generator中
    var gen = function*() {
    var data = yield readFile('./file1');
    console.log(data.toString());
    data = yield readFile('./file2');
    console.log(data.toString());
    }
    //手動執行generator
    var g = gen();
    var another = g.next();
    //another.value就是返回的promise對象
    another.value.then(function(data) {
    //再次調用g.next從斷點處執行generator,并將data作為參數傳回
    var another2 = g.next(data);
    another2.value.then(function(data) {
    g.next(data);
    })
    })

    上述代碼中,我們在generator中yield了readFile,回調語句代碼寫在yield之后的代碼中,完全是同步的寫法,實現了文章一開頭的設想。

    而yield之后,我們得到的是一個another.value是一個promise對象,我們可以使用then語句定義回調函數,函數的內容呢,則是將讀取到的data返回給generator并繼續讓generator從斷點處執行。

    基本上這就是異步回調同步化最核心的原理,事實上如果大家熟悉python,會知道python中有"協程"的概念,基本上也是使用generator來實現的(我想當懷疑es6的generator就是借鑒了python~)

    不過呢,上述代碼我們依然是手動執行的。那么同上一篇一樣,我們還需要實現一個run函數,用于管理generator的流程,讓它能夠自動跑起來!

    3. 讓同步化回調函數自動跑起來:一個run函數的編寫

    仔細觀察上一段代碼中手動執行generator的部分,也能發現一個規律,這個規律讓我們可以直接寫一個遞歸的函數來代替:

    var run=function(gen){
    var g;
    if(typeof gen.next==='function'){
    g=gen;
    }else{
    g=gen();
    }
    function next(data){
    var tmp=g.next(data);
    if(tmp.done){
    return ;
    }else{
    tmp.value.then(next);
    }
    }
    next();
    }

    函數接收一個generator,并讓其中的異步能夠自動執行。使用這個run函數,我們來讓上一個異步代碼自動執行:

    var fs = require('fs');
    var run = function(gen) {
    var g;
    if (typeof gen.next === 'function') {
    g = gen;
    } else {
    g = gen();
    }
    function next(data) {
    var tmp = g.next(data);
    if (tmp.done) {
    return;
    } else {
    tmp.value.then(next);
    }
    }
    next();
    }
    var readFile = function(fileName) {
    return new Promise(function(resolve, reject) {
    fs.readFile(fileName, function(err, data) {
    if (err) {
    reject(err);
    } else {
    resolve(data);
    }
    })
    })
    }
    //將讀文件的過程放在generator中
    var gen = function*() {
    var data = yield readFile('./file1');
    console.log(data.toString());
    data = yield readFile('./file2');
    console.log(data.toString());
    }
    //下面只需要將gen放入run當中即可自動執行
    run(gen);

    執行上述代碼,即可看到終端依次打印出了file1和file2的內容。

    需要指出的是,這里的run函數為了簡單起見只支持promise,而實際的co函數還支持thunk等。

    這樣一來,co函數的兩大功能基本就完整介紹了,一個是洋蔥模型的流程控制,另一個是異步同步化代碼的自動執行。在下一篇文章中,我將帶大家對這兩個功能進行整合,寫出我們自己的一個co函數!

    這篇文章的代碼同樣可以在github上面找到:https://github.com/mly-zju/async-js-demo,其中promise_generator.js就是本篇的示例源碼。

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    深入解析koa之異步回調處理

    深入解析koa之異步回調處理:1. 回調金字塔及理想中的解決方案 我們都知道javascript是一門單線程異步非阻塞語言。異步非阻塞當然是它的一個優點,但大量的異步操作必然涉及大量的回調函數,特別是當異步嵌套的時候,就會出現回調金字塔的問題,使得代碼的可讀性非常差。比如下面一個例
    推薦度:
    標簽: 回調 異步 Koa
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产精品无码素人福利| 日韩精品毛片| 亚洲精品久久久www| 88国产精品欧美一区二区三区| 亚洲AV无码国产精品色午友在线| 国产精品亚洲综合一区| 国产精品一国产精品| 久久久久无码精品国产不卡| 亚洲爆乳精品无码一区二区| 黑巨人与欧美精品一区| 亚洲欧洲国产精品你懂的| 国产精品成人A区在线观看| 亚洲精品制服丝袜四区| 日韩精品亚洲专区在线观看| 国产精品伊人久久伊人电影| 国产精品爱搞视频网站| 91精品国产高清久久久久久国产嫩草| 高清在线亚洲精品国产二区| 国产精品亚洲成在人线| 精品人妻中文字幕有码在线| 少妇精品无码一区二区三区| 亚洲国产一成人久久精品| 亚洲精品自产拍在线观看| 最新国产精品精品视频| 亚洲国产精品成人午夜在线观看| 久久久久人妻一区精品果冻| 久久国产精品免费一区二区三区| 国产精品自在线拍国产第一页 | 亚洲午夜精品第一区二区8050| 九九线精品视频在线观看| 国内精品国产成人国产三级| 老司机午夜网站国内精品久久久久久久久 | 亚洲国产婷婷综合在线精品| 无码欧精品亚洲日韩一区夜夜嗨| 日本精品久久久久影院日本| 亚洲国产精品自产在线播放| 中文字幕一精品亚洲无线一区| 亚洲精品国偷自产在线| 日韩精品国产另类专区| 国产精品白丝AV网站| 国产精品视频一区国模私拍|