亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

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

2024-05-06 16:52:17
字體:
來源:轉載
供稿:網友

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就是本篇的示例源碼。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91在线视频九色| 91久久精品久久国产性色也91| 色综合伊人色综合网| 久久综合九色九九| 91亚洲国产精品| 7777精品久久久久久| 欧美成人亚洲成人日韩成人| 夜夜躁日日躁狠狠久久88av| 北条麻妃一区二区三区中文字幕| 91牛牛免费视频| 亚洲一二在线观看| 精品久久久久久久久中文字幕| 国产一区二区三区直播精品电影| 亚洲a成v人在线观看| 日韩中文字幕在线播放| 日韩美女毛茸茸| 国产精品户外野外| 久久av在线播放| 欧美性感美女h网站在线观看免费| 国产一区二区三区视频免费| 热门国产精品亚洲第一区在线| 久久视频在线观看免费| 国产精品午夜国产小视频| 一个色综合导航| 亚洲毛片在线免费观看| 国产精品久在线观看| 亚洲欧美日韩久久久久久| 91免费视频国产| 亚洲欧美精品中文字幕在线| 亚洲一区二区三区四区视频| 美女久久久久久久| 欧美成人精品在线观看| 最近2019中文字幕一页二页| 亚洲国产天堂久久综合网| 亚洲精品色婷婷福利天堂| 国产日韩在线看片| 国产精品第一页在线| 九九热最新视频//这里只有精品| 欧美一区二区三区免费视| 欧美激情视频一区二区三区不卡| 热99久久精品| 日韩精品高清在线观看| 久久视频在线视频| 久久久亚洲精选| 欧美视频在线免费看| 欧美精品一区三区| 成人www视频在线观看| 久久中文字幕一区| 精品美女国产在线| 日韩一区在线视频| 成人国产精品一区二区| 91精品啪在线观看麻豆免费| 亚洲综合日韩中文字幕v在线| 欧美美女15p| 色黄久久久久久| 国产成人精品视| 欧美精品久久一区二区| 日产精品久久久一区二区福利| 亚洲最大的网站| 91在线视频导航| 日本欧美一级片| 日日摸夜夜添一区| 中文字幕亚洲一区二区三区| 久久影视三级福利片| 亚洲精品短视频| 狠狠躁夜夜躁人人爽天天天天97| 久久精品免费电影| 欧美成aaa人片在线观看蜜臀| 亚洲国产欧美精品| 久久精品久久久久久国产 免费| 日韩美女免费线视频| 91精品综合久久久久久五月天| 欧美精品18videos性欧| 国产精品大陆在线观看| 欧美另类交人妖| 欧美精品在线看| 岛国精品视频在线播放| 日韩av不卡在线| 成人免费视频网| 国产一区二区三区在线观看视频| 少妇av一区二区三区| 国产va免费精品高清在线| 久久久久久国产精品美女| 国产精品久久久久久亚洲影视| 91av在线视频观看| 日韩av在线免费播放| 成人情趣片在线观看免费| 亚洲综合视频1区| 亚洲专区国产精品| 琪琪第一精品导航| 国产精品十八以下禁看| 国产91免费观看| 成人黄色av网站| 亚洲综合中文字幕在线观看| 国产精品嫩草影院久久久| 亚洲精品免费在线视频| 日韩精品久久久久久福利| 97在线日本国产| 黑人极品videos精品欧美裸| 国产亚洲欧美日韩精品| 国产日本欧美在线观看| 国产日韩欧美视频| 亚洲片在线资源| 亚洲一区二区久久久久久久| 日韩欧美a级成人黄色| 88国产精品欧美一区二区三区| 日韩国产精品亚洲а∨天堂免| 宅男66日本亚洲欧美视频| 国产精品入口免费视| 在线观看亚洲视频| 久久国产精彩视频| 欧美视频免费在线| 欧美精品videosex牲欧美| 91精品国产综合久久久久久久久| 欧美日韩国产成人在线| 成人福利网站在线观看11| 国产亚洲欧美日韩一区二区| 国产午夜精品全部视频播放| 欧美最顶级丰满的aⅴ艳星| 国产精品视频中文字幕91| 91精品视频免费观看| 欧美日韩亚洲一区二区三区| 久久精品国产视频| 欧美性感美女h网站在线观看免费| 亚洲成人精品久久久| 久久手机精品视频| 欧美韩国理论所午夜片917电影| 亚洲品质视频自拍网| 亚洲色图17p| 国语自产在线不卡| 国产乱肥老妇国产一区二| 亚洲最大激情中文字幕| 亚洲天堂av在线播放| 亚洲香蕉成人av网站在线观看| 中文字幕精品久久| 久久亚洲精品国产亚洲老地址| 一区二区国产精品视频| 久久久久久久久国产精品| 欧美成人网在线| 精品中文字幕久久久久久| 久久久久久九九九| 亚洲福利视频在线| 亚洲成**性毛茸茸| 欧美成人激情图片网| 97精品国产aⅴ7777| 欧美久久精品午夜青青大伊人| 国产精品日日摸夜夜添夜夜av| 欧美日在线观看| 青草青草久热精品视频在线观看| 欧美日韩成人在线观看| 亚洲人永久免费| 神马国产精品影院av| 日本精品视频网站| 久久久人成影片一区二区三区| 深夜福利日韩在线看| 91免费看片在线| 操日韩av在线电影| 久久精品国产欧美亚洲人人爽| 欧美成人精品在线观看| 欧美精品久久久久久久久久| 中文字幕日韩精品在线| 91亚洲国产精品| 中文字幕欧美日韩| 亚洲另类激情图|