2019-10-30Node.js異步編程

1.1同步API夺溢,異步API

當(dāng)中的API:有的通過返回值拿到結(jié)果,有的通過函數(shù)返回值方式拿到結(jié)果为流。
例如:

// 返回值拿到
// 路徑拼接
const public = path.join(__dirname,'public');
// 請(qǐng)求地址解析
const urlObj = url.parse(req.url);
// 函數(shù)返回值
// 讀取文件
fs.readFile('./demo.txt,'utf8',(err,result)=>{
         console.log(result);
});

為什么會(huì)有這兩種方式酸茴?
===============================.
什么是同步API?
只有當(dāng)前API執(zhí)行完成后沼本,才能繼續(xù)執(zhí)行下一個(gè)API
例如:

console.log('before');
console.log('after');
// 只有第一個(gè)執(zhí)行完噩峦,才能執(zhí)行第二個(gè)。這就是同步API抽兆,代碼從上到下一行一行的執(zhí)行识补,只有上一行代碼執(zhí)行完成,才能執(zhí)行下一行代碼郊丛。

什么是異步API李请?
當(dāng)前API的執(zhí)行瞧筛,不會(huì)阻塞后面代碼的執(zhí)行!
例如:

console.log('before');
setTimeout(
()=>{console.log('last');
},2000)
console.log('after');
// 結(jié)果:先輸出before,再輸出after,2s后輸出了last导盅,(PS:雖然定時(shí)器代碼在after前面较幌,但是程序在執(zhí)行到定時(shí)器代碼時(shí),并沒有等待定時(shí)器代碼執(zhí)行完成白翻,再執(zhí)行after這個(gè)方法乍炉,在當(dāng)前代碼中定時(shí)器就是異步API,程序不需要等待異步API執(zhí)行完成之后滤馍,再繼續(xù)執(zhí)行后面的代碼岛琼,也就是說異步API不會(huì)阻塞后續(xù)代碼的執(zhí)行。)

在Node.js中異步API無(wú)處不在巢株,掌握異步異步API槐瑞,異步編程非常重要。

1.2同步API阁苞,異步API的區(qū)別(獲取返回值)

同步API可以從返回值中拿到API執(zhí)行的結(jié)果困檩,但是異步API不可以。
例子:

// 同步
function sum (n1 ,n2){
         return n1 + n2;
}
const result =  sum(10,20);

// 異步
function getMsg(){
    setTimeout(function(){
         return{msg:'Hello Node,js'}
    },2000);
    //return undefined
}
const msg = getMsg();
console.log(msg);      

思考:是否能拿到函數(shù)返回值那槽?

執(zhí)行后返回: undefind

PS: 原因:當(dāng)使用函數(shù)名getMsg函數(shù)名去調(diào)用getMsg()函數(shù)時(shí)悼沿,由于異步API不會(huì)阻塞代碼的執(zhí)行,所以在函數(shù)的底部直接return undefind(PS:因?yàn)闆]有寫return骚灸,所以他默認(rèn)返回的就是undefined,然后再過2秒后糟趾,他在setTimeout函數(shù)內(nèi)部返回了一個(gè)對(duì)象,此時(shí)返回值早已拿到了undefined,然后直接進(jìn)行了輸出)

結(jié)論:在異步API中甚牲,無(wú)法通過返回值的方式去拿到異步API的執(zhí)行結(jié)果义郑。

1.3回調(diào)函數(shù)

那么異步API的返回值到底該怎么拿到?
實(shí)際上是通過回調(diào)函數(shù)拿到的,什么是回調(diào)函數(shù)鳖藕,實(shí)際上就是自己定義函數(shù)魔慷,讓別人去調(diào)用函數(shù)(看下面例子))

// getData函數(shù)定義
function getData(callback){}
//getData函數(shù)調(diào)用
getData(()=>{});
// callback僅僅是形參的名字,那么這個(gè)形參對(duì)應(yīng)的實(shí)參實(shí)際上是一個(gè)函數(shù)著恩,將一個(gè)函數(shù)作為另外一個(gè)函數(shù)的參數(shù)(沒有問題)院尔,callback就是一個(gè)回調(diào)函數(shù),在調(diào)用getData的時(shí)候傳遞了一個(gè)匿名函數(shù)(函數(shù)的定義喉誊,實(shí)際上這個(gè)函數(shù)在getData方法的內(nèi)部調(diào)用邀摆,根據(jù)實(shí)際的情況決定是否要調(diào)用,來(lái)決定什么是要調(diào)用伍茄,這個(gè)參數(shù)就是回到函數(shù))栋盹。

在代碼編輯器中新建一個(gè)文件callback.js

function getData(callback){
    callback();
}
getData(function(){
    console.log('callback函數(shù)被調(diào)用了')
});

命令行工具執(zhí)行node callback.js

返回:callback函數(shù)被調(diào)用了
// 這就是回調(diào)函數(shù)其中一種表現(xiàn)形式

函數(shù)寫成這個(gè)樣子有什么用?

function getData(callback){
    callback('123');              // 給callback傳遞參數(shù) 123
}
getData(function(n){          // 在這個(gè)函數(shù)里拿到123這個(gè)實(shí)參敷矫,使用形參n對(duì)象這個(gè)實(shí)參
    console.log('callback函數(shù)被調(diào)用了')
    console.log(n)例获;
});

返回:callback函數(shù)被調(diào)用了
123

PS:123被輸出了妇多。如果getData這個(gè)函數(shù)在內(nèi)部有異步操作鲸郊,在異步操作執(zhí)行完成之后古今,就可以調(diào)用callback('123')這個(gè)回調(diào)函數(shù)轮蜕,并且把異步API執(zhí)行的結(jié)果通過參數(shù)的形式傳遞給callback,那么我們?cè)趃etData里面的回調(diào)函數(shù)里面就能夠拿到異步API執(zhí)行的結(jié)果收壕。

回到第一個(gè)例子:

function getMsg(callback){
    setTimeout(function(){
       callback({
            msg:'hello node.js'
    }) 
    },2000);
}
getMsg(function(data){
  console.log(data);
});    

命令行執(zhí)行

返回:{mag:'hello node.js'}
PS:通過回調(diào)函數(shù)的方式拿到了異步API執(zhí)行的結(jié)果妓灌。

1.4同步API,異步API的區(qū)別(代碼執(zhí)行順序)

同步API從上到下一次執(zhí)行蜜宪,前面代碼沒有執(zhí)行完成之前虫埂,后面的代碼不能執(zhí)行

for(var i=0;i<100000;i++){
console.log(i);
}
console.log('for循環(huán)后面的代碼');

PS:先執(zhí)行for循環(huán)10萬(wàn)次圃验,在for循環(huán)沒有執(zhí)行完成之前掉伏,后面的console.log()是不能執(zhí)行的。

異步API不會(huì)等待API執(zhí)行完成后再向下執(zhí)行

console.log('代碼開始執(zhí)行');
setTiomeout(()=>{console.log('2S后執(zhí)行的代碼')}损谦,2000)岖免;
setTiomeout(()=>{console.log('0S后執(zhí)行的代碼')},0)照捡;
console.log('代碼結(jié)束執(zhí)行');

返回:代碼開始執(zhí)行
代碼結(jié)束執(zhí)行
0S后執(zhí)行的代碼
2S后執(zhí)行的代碼

總結(jié):同步代碼執(zhí)行區(qū)→異步代碼執(zhí)行區(qū)→回調(diào)函數(shù)隊(duì)列
同步執(zhí)行完成后,再異步代碼執(zhí)行區(qū)執(zhí)行(完成后)话侧,再去回調(diào)函數(shù)隊(duì)列栗精,再將隊(duì)列中的回調(diào)函數(shù)放入同步代碼執(zhí)行區(qū)執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瞻鹏,一起剝皮案震驚了整個(gè)濱河市悲立,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌新博,老刑警劉巖薪夕,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異赫悄,居然都是意外死亡原献,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門埂淮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)姑隅,“玉大人,你說我怎么就攤上這事倔撞〗惭觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵痪蝇,是天一觀的道長(zhǎng)鄙陡。 經(jīng)常有香客問我冕房,道長(zhǎng),這世上最難降的妖魔是什么趁矾? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任耙册,我火速辦了婚禮,結(jié)果婚禮上愈魏,老公的妹妹穿的比我還像新娘觅玻。我一直安慰自己,他們只是感情好培漏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布溪厘。 她就那樣靜靜地躺著,像睡著了一般牌柄。 火紅的嫁衣襯著肌膚如雪畸悬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天珊佣,我揣著相機(jī)與錄音蹋宦,去河邊找鬼。 笑死咒锻,一個(gè)胖子當(dāng)著我的面吹牛冷冗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播惑艇,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蒿辙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了滨巴?” 一聲冷哼從身側(cè)響起思灌,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恭取,沒想到半個(gè)月后泰偿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜈垮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年耗跛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片窃款。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡课兄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晨继,到底是詐尸還是另有隱情烟阐,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站蜒茄,受9級(jí)特大地震影響唉擂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜檀葛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一玩祟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屿聋,春花似錦空扎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至楚殿,卻和暖如春撮慨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背脆粥。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工砌溺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人变隔。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓规伐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親匣缘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子楷力,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 弄懂js異步 講異步之前,我們必須掌握一個(gè)基礎(chǔ)知識(shí)-event-loop孵户。 我們知道JavaScript的一大特點(diǎn)...
    DCbryant閱讀 2,706評(píng)論 0 5
  • topics: 1.The Node.js philosophy 2.The reactor pattern 3....
    宮若石閱讀 1,061評(píng)論 0 1
  • 概要 64學(xué)時(shí) 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,125評(píng)論 0 3
  • Node.js 常用工具 util 是一個(gè)Node.js 核心模塊,提供常用函數(shù)的集合岔留,用于彌補(bǔ)核心JavaScr...
    FTOLsXD閱讀 530評(píng)論 0 2
  • Promise 對(duì)象 Promise 的含義 Promise 是異步編程的一種解決方案夏哭,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,702評(píng)論 1 56