国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專(zhuān)題視頻專(zhuān)題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專(zhuān)題1關(guān)鍵字專(zhuān)題50關(guān)鍵字專(zhuān)題500關(guān)鍵字專(zhuān)題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關(guān)鍵字專(zhuān)題關(guān)鍵字專(zhuān)題tag2tag3文章專(zhuān)題文章專(zhuān)題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專(zhuān)題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

深入解析koa之異步回調(diào)處理

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 21:54:59
文檔

深入解析koa之異步回調(diào)處理

深入解析koa之異步回調(diào)處理:1. 回調(diào)金字塔及理想中的解決方案 我們都知道javascript是一門(mén)單線程異步非阻塞語(yǔ)言。異步非阻塞當(dāng)然是它的一個(gè)優(yōu)點(diǎn),但大量的異步操作必然涉及大量的回調(diào)函數(shù),特別是當(dāng)異步嵌套的時(shí)候,就會(huì)出現(xiàn)回調(diào)金字塔的問(wèn)題,使得代碼的可讀性非常差。比如下面一個(gè)例
推薦度:
導(dǎo)讀深入解析koa之異步回調(diào)處理:1. 回調(diào)金字塔及理想中的解決方案 我們都知道javascript是一門(mén)單線程異步非阻塞語(yǔ)言。異步非阻塞當(dāng)然是它的一個(gè)優(yōu)點(diǎn),但大量的異步操作必然涉及大量的回調(diào)函數(shù),特別是當(dāng)異步嵌套的時(shí)候,就會(huì)出現(xiàn)回調(diào)金字塔的問(wèn)題,使得代碼的可讀性非常差。比如下面一個(gè)例

1. 回調(diào)金字塔及理想中的解決方案

我們都知道javascript是一門(mén)單線程異步非阻塞語(yǔ)言。異步非阻塞當(dāng)然是它的一個(gè)優(yōu)點(diǎn),但大量的異步操作必然涉及大量的回調(diào)函數(shù),特別是當(dāng)異步嵌套的時(shí)候,就會(huì)出現(xiàn)回調(diào)金字塔的問(wèn)題,使得代碼的可讀性非常差。比如下面一個(gè)例子:

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

這個(gè)例子是先后讀取兩個(gè)文件內(nèi)容并打印,其中file2的讀取必須在file1讀取結(jié)束之后再進(jìn)行,因此其操作必須要在file1讀取的回調(diào)函數(shù)中執(zhí)行。這是一個(gè)典型的回調(diào)嵌套,并且只有兩層而已,在實(shí)際編程中,我們可能會(huì)遇到更多層的嵌套,這樣的代碼寫(xiě)法無(wú)疑是不夠優(yōu)雅的。

在我們想象中,比較優(yōu)雅的一種寫(xiě)法應(yīng)該是看似同步實(shí)則異步的寫(xiě)法,類(lèi)似下面這樣:

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

這樣的寫(xiě)法,就完全避免回調(diào)地獄。事實(shí)上,koa就讓我們可以使用這樣的寫(xiě)法來(lái)寫(xiě)異步回調(diào)函數(shù):

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

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

2. generator配合promise實(shí)現(xiàn)異步回調(diào)同步寫(xiě)法

關(guān)鍵的一點(diǎn),其實(shí)前一篇也提到了,就是generator具有類(lèi)似"打斷點(diǎn)"這樣的效果。當(dāng)遇到y(tǒng)ield的時(shí)候,就會(huì)暫停,將控制權(quán)交給yield后面的函數(shù),當(dāng)下次返回的時(shí)候,再繼續(xù)執(zhí)行。

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

今天的文章中,我們就以promise為例來(lái)進(jìn)行分析,看看如何使用generator和promise配合,實(shí)現(xiàn)異步同步化。

依舊以第一個(gè)讀取文件例子來(lái)分析。首先,我們需要將讀文件的函數(shù)進(jìn)行改造,將其封裝成為一個(gè)promise對(duì)象:

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());
})

關(guān)于promise的使用,如果不熟悉的可以去看看es6中的語(yǔ)法。(近期我也會(huì)寫(xiě)一篇文章來(lái)教大家如何用es5的語(yǔ)法來(lái)自己實(shí)現(xiàn)一個(gè)具備基本功能的promise對(duì)象,敬請(qǐng)期待呦^_^)

簡(jiǎn)單來(lái)講,promise可以實(shí)現(xiàn)將回調(diào)函數(shù)通過(guò) promise.then(callback)的形式來(lái)寫(xiě)。但是我們的目標(biāo)是配合generator,真正實(shí)現(xiàn)如絲般順滑的同步化寫(xiě)法,如何配合呢,看這段代碼:

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);
}
})
})
}
//將讀文件的過(guò)程放在generator中
var gen = function*() {
var data = yield readFile('./file1');
console.log(data.toString());
data = yield readFile('./file2');
console.log(data.toString());
}
//手動(dòng)執(zhí)行g(shù)enerator
var g = gen();
var another = g.next();
//another.value就是返回的promise對(duì)象
another.value.then(function(data) {
//再次調(diào)用g.next從斷點(diǎn)處執(zhí)行g(shù)enerator,并將data作為參數(shù)傳回
var another2 = g.next(data);
another2.value.then(function(data) {
g.next(data);
})
})

上述代碼中,我們?cè)趃enerator中yield了readFile,回調(diào)語(yǔ)句代碼寫(xiě)在yield之后的代碼中,完全是同步的寫(xiě)法,實(shí)現(xiàn)了文章一開(kāi)頭的設(shè)想。

而yield之后,我們得到的是一個(gè)another.value是一個(gè)promise對(duì)象,我們可以使用then語(yǔ)句定義回調(diào)函數(shù),函數(shù)的內(nèi)容呢,則是將讀取到的data返回給generator并繼續(xù)讓generator從斷點(diǎn)處執(zhí)行。

基本上這就是異步回調(diào)同步化最核心的原理,事實(shí)上如果大家熟悉python,會(huì)知道python中有"協(xié)程"的概念,基本上也是使用generator來(lái)實(shí)現(xiàn)的(我想當(dāng)懷疑es6的generator就是借鑒了python~)

不過(guò)呢,上述代碼我們依然是手動(dòng)執(zhí)行的。那么同上一篇一樣,我們還需要實(shí)現(xiàn)一個(gè)run函數(shù),用于管理generator的流程,讓它能夠自動(dòng)跑起來(lái)!

3. 讓同步化回調(diào)函數(shù)自動(dòng)跑起來(lái):一個(gè)run函數(shù)的編寫(xiě)

仔細(xì)觀察上一段代碼中手動(dòng)執(zhí)行g(shù)enerator的部分,也能發(fā)現(xiàn)一個(gè)規(guī)律,這個(gè)規(guī)律讓我們可以直接寫(xiě)一個(gè)遞歸的函數(shù)來(lái)代替:

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();
}

函數(shù)接收一個(gè)generator,并讓其中的異步能夠自動(dòng)執(zhí)行。使用這個(gè)run函數(shù),我們來(lái)讓上一個(gè)異步代碼自動(dòng)執(zhí)行:

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);
}
})
})
}
//將讀文件的過(guò)程放在generator中
var gen = function*() {
var data = yield readFile('./file1');
console.log(data.toString());
data = yield readFile('./file2');
console.log(data.toString());
}
//下面只需要將gen放入run當(dāng)中即可自動(dòng)執(zhí)行
run(gen);

執(zhí)行上述代碼,即可看到終端依次打印出了file1和file2的內(nèi)容。

需要指出的是,這里的run函數(shù)為了簡(jiǎn)單起見(jiàn)只支持promise,而實(shí)際的co函數(shù)還支持thunk等。

這樣一來(lái),co函數(shù)的兩大功能基本就完整介紹了,一個(gè)是洋蔥模型的流程控制,另一個(gè)是異步同步化代碼的自動(dòng)執(zhí)行。在下一篇文章中,我將帶大家對(duì)這兩個(gè)功能進(jìn)行整合,寫(xiě)出我們自己的一個(gè)co函數(shù)!

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

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

深入解析koa之異步回調(diào)處理

深入解析koa之異步回調(diào)處理:1. 回調(diào)金字塔及理想中的解決方案 我們都知道javascript是一門(mén)單線程異步非阻塞語(yǔ)言。異步非阻塞當(dāng)然是它的一個(gè)優(yōu)點(diǎn),但大量的異步操作必然涉及大量的回調(diào)函數(shù),特別是當(dāng)異步嵌套的時(shí)候,就會(huì)出現(xiàn)回調(diào)金字塔的問(wèn)題,使得代碼的可讀性非常差。比如下面一個(gè)例
推薦度:
標(biāo)簽: 回調(diào) 異步 Koa
  • 熱門(mén)焦點(diǎn)

最新推薦

猜你喜歡

熱門(mén)推薦

專(zhuān)題
Top
主站蜘蛛池模板: 亚洲欧美日韩另类精品一区二区三区 | 欧美高清一区二区 | 一道精品视频一区二区三区男同 | 久久国产夜色精品噜噜亚洲a | 亚洲高清在线视频 | 国产精品资源在线观看 | 一级毛片特级毛片免费的 | 国产免费观看视频 | 国产网站在线看 | 91亚洲欧美综合高清在线 | 色网站在线看 | 精品久久久久久国产牛牛app | 美女视频黄a视频全免费网站色 | 久久伊人五月天 | 亚洲国产成人久久综合野外 | 日本色图在线观看 | 久久艹精品 | 欧美高清a| 永久免费毛片 | 久久久久久91精品色婷婷 | 国产三级一区 | 久久精品a亚洲国产v高清不卡 | 国产成人精品999在线 | 日韩亚洲视频 | 亚洲综合小说 | 亚欧美色| 国产亚洲精品一品区99热 | 国产91久久精品一区二区 | 日韩成人在线电影 | 深夜福利一区二区 | 国产精品免费_区二区三区观看 | 亚洲人一区 | 日韩视频免费在线观看 | 免费观看性欧美大片 | 亚洲电影中文字幕 | 亚洲国产精品成人久久 | 国内精品在线视频 | 亚洲精品在线免费观看 | 国产成人欧美一区二区三区的 | 日本a级无毛 | 国产欧美综合精品一区二区 |