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

1.1Node,js中的異步API

// 讀取文件操作
fs.readFile('./demo.txt',(eer,result)=>{});
// 事件監(jiān)聽API
var server = http.creatServer;
server.on('request',(req,res)=>{});

如果異步API后面的代碼執(zhí)行依賴當前異步API的執(zhí)行結(jié)果桑包,但實際上后續(xù)代碼在執(zhí)行的時候異步API還沒有返回結(jié)果,這個問題怎么解決事哭?
fs.readFile('./demo.txt',(eer,result)=>{});
console.log('文件讀取結(jié)果');
解決辦法:①把console.log()放在回調(diào)函數(shù)中
問題赚抡?需求蠢甲,依次讀取A文件,B文件滥崩,C文件(如果使用①的解決辦法,那么函數(shù)會嵌套太多讹语,難以維護)钙皮。
新建文件1.txt,2.txt,3.txt

const fs = require('fs')
fs.readFile('./1.txt','utf8',(err,result1)=>{
    console.log(result1);
    fs.readFile('./2.txt','utf8',(err,result2)=>{
        console.log(result2);     
        fs.readFile('./3.txt','utf8',(err,result3)=>{
            console.log(result3);    
        });
    });
});

返回:1
2
3

PS:這樣的代碼叫做回調(diào)地獄,雖然能解決需求顽决,但難以維護短条。es6中提供了promise可以解決回調(diào)地獄的問題。

1.2promise解決回調(diào)地獄

基礎語法

let promise = new Promise((resolve,reject)=>{     // resolve成功才菠,reject執(zhí)行失敗信息
    setTimeout(()=>{
        if(true){
            resolve({name,'張三'})
        }else{
            reject('失敗了');
        }
    },2000);
});
promise.then(result=>console.log(result);)   // { name:'張三'}
               .catch(error=>console.log(error);)   // 失敗了

新建文件7.promise.js

const fs =require('fs');
let promise = new Promise((resolve,reject)=>{
   fs.readFile('./100.txt','utf8',(err,result)=>{
       if(err !=null){
           reject(err);
       }else{
           resolve(result);
       }
   });
});
promise.then((result)=>{
   console.log(result); 
})
.catch((err)=>{
console.log(err);
})

返回[Error: ENOENT: no such file or directory, open 'C:\Node\100.txt'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\Node\100.txt'
}

通過catch拿到異步API的錯誤信息茸时,此時能夠把異步API的執(zhí)行,和錯誤的處理進行了分離赋访,使用這樣的方式就能解決回調(diào)地獄的問題可都。
新建8.promise2.js文件

 const fs = require('fs')
// fs.readFile('./1.txt','utf8',(err,result1)=>{
//     console.log(result1);
//     fs.readFile('./2.txt','utf8',(err,result2)=>{
//         console.log(result2);     
//         fs.readFile('./3.txt','utf8',(err,result3)=>{
//             console.log(result3);    
//         });
//     });
// });

function p1(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./1.txt','utf8',(err,result)=>{
            resolve(result);    
        });
    })
}
function p2(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./2.txt','utf8',(err,result)=>{
            resolve(result);    
        });
    })
}
function p3(){
    return new Promise((resolve,reject)=>{
        fs.readFile('./3.txt','utf8',(err,result)=>{
            resolve(result);  
        });
    })
}
p1().then((r1)=>{
console.log(r1);
return p2();
})
.then((r2)=>{
    console.log(r2);
    return p3();
})
.then((r3)=>{
    console.log(r3);
})

返回1 2 3

1.3異步函數(shù)(ES7)

基于promise對象的基礎上進行封裝,將看起來比較臃腫的代碼封裝起來蚓耽,開發(fā)一些關鍵字渠牲,供我們使用。
異步函數(shù)是異步編程語法的終極解決方案步悠,他可以讓我們將異步代碼寫成同步形式签杈,讓代碼不再有回調(diào)函數(shù)嵌套,使代碼變得清晰明了鼎兽。
語法:

const fn = async()=>{};
async function fn(){}

新建文件9.async.js

// 1.在普通函數(shù)定義的前面加上async關鍵字答姥,普通函數(shù)就變成了異步函數(shù)
// 2.異步函數(shù)默認的返回值是promise對象
// 3.在異步函數(shù)內(nèi)部使用throw關鍵字進行錯誤拋出
// 4.await關鍵字    PS:1.它只能出現(xiàn)在異步函數(shù)中2.await promise 他可以暫停異步函數(shù)的執(zhí)行,等待promise對象返回結(jié)果后再向下執(zhí)行函數(shù)谚咬。
async function fn(){
}
console.log(fn())

返回:Promise{undefined}

async function fn(){
    return 123
}
console.log(fn())

返回:Promise{123}

async function fn(){
    return 123
}
fn().then(function(data){
    console.log(data);
})

返回:Promise{123}

錯誤信息怎么返回鹦付?以前是用reject,現(xiàn)在用throw關鍵字序宦。

async function fn(){
    throw '發(fā)生了一些錯誤';    // throw一旦執(zhí)行后面的代碼就無法執(zhí)行了
    return 123
}
fn().then(function(data){
    console.log(data);
})
.catch(function(err){      // err就是throw后面的文字
    console.log(err)
})

返回:發(fā)生了一些錯誤

使用await關鍵字

async function = p1(){
   return 'p1';
}
async function = p2(){
   return 'p2';
}
async function = p3(){
   return 'p3';
}
async function run(){
   let r1 = await p1()                        // 使用了await如果P1沒有結(jié)果不會向下執(zhí)行
   let r2 = await p2()
   let r3 = await p3()
   console.log(r1)
   console.log(r2)
   console.log(r3)
}
run()

返回:p1
p2
p3

async關鍵字
1.普通函數(shù)定義前加async關鍵字睁壁, 普通函數(shù)就變成了異步函數(shù)
2.異步函數(shù)默認返回promise對象
3.在異步函數(shù)內(nèi)部使用return關鍵字進行結(jié)果返回,結(jié)果會被包裹的promise對象中互捌,return關鍵字代替了resolve方法
4.在異步函數(shù)內(nèi)部使用throw關鍵字拋出程序異常
5.調(diào)用異步函數(shù)在鏈式調(diào)用then方法獲取異步函數(shù)執(zhí)行結(jié)果
6.調(diào)用異步函數(shù)再鏈式調(diào)用catch方法獲取異步函數(shù)執(zhí)行的錯誤信息

await關鍵字
1.await關鍵字只能出現(xiàn)在異步函數(shù)中
2.await promise await后面只能寫promise對象潘明,寫其他類型API是不可以的
3.await關鍵字可暫停異步函數(shù)向下執(zhí)行,指定promise返回結(jié)果

異步函數(shù)在Node.js中的應用

新建anyac目錄下新建文件anyncfunction.js

PS:redFile是通過返回值的方式秕噪,來獲取文件的讀取結(jié)果钳降,也就是它不返回promise對象,readFile前面不能加await關鍵字腌巾,因為它不返回promise對象遂填,也就是異步函數(shù)中node.js不能用铲觉。
后來node.js提供了一個方法,能對現(xiàn)有的異步API進行包裝吓坚,讓這個方法去返回promise對象撵幽,以支持異步函數(shù)語法。

這個方法叫做 promisify礁击,它存儲在了util模塊中

const fs= require('fs');
// 改造現(xiàn)有異步函數(shù)API盐杂,讓其返回promise對象從而支持異步函數(shù)語法
const promisify = require('util').promisify;
// promisify(fs.readFile)                  // 返回一個新的讀取文件的方法
// 調(diào)用promisify方法改造現(xiàn)有異步API,讓其返回promise對象
const readFile = promisify(fs.readFile)      

async function run(){
    let r1 = await readFile('./1.txt','utf8')
    let r2 = await readFile('./2.txt','utf8')
    let r3 = await readFile('./3.txt','utf8')
    console.log(r1);
    console.log(r2);
    console.log(r3);
}

run();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哆窿,一起剝皮案震驚了整個濱河市链烈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挚躯,老刑警劉巖强衡,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異码荔,居然都是意外死亡漩勤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門目胡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锯七,“玉大人,你說我怎么就攤上這事誉己∶际” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵巨双,是天一觀的道長噪猾。 經(jīng)常有香客問我,道長筑累,這世上最難降的妖魔是什么袱蜡? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮慢宗,結(jié)果婚禮上坪蚁,老公的妹妹穿的比我還像新娘。我一直安慰自己镜沽,他們只是感情好敏晤,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缅茉,像睡著了一般嘴脾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天译打,我揣著相機與錄音耗拓,去河邊找鬼。 笑死奏司,一個胖子當著我的面吹牛乔询,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播韵洋,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼哥谷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了麻献?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤猜扮,失蹤者是張志新(化名)和其女友劉穎勉吻,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旅赢,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡齿桃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了了嚎。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片前翎。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡缚忧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出香到,到底是詐尸還是另有隱情,我是刑警寧澤报破,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布悠就,位于F島的核電站,受9級特大地震影響充易,放射性物質(zhì)發(fā)生泄漏梗脾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一盹靴、第九天 我趴在偏房一處隱蔽的房頂上張望炸茧。 院中可真熱鬧,春花似錦稿静、人聲如沸梭冠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妈嘹。三九已至,卻和暖如春绍妨,著一層夾襖步出監(jiān)牢的瞬間润脸,已是汗流浹背柬脸。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留毙驯,地道東北人倒堕。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像爆价,于是被迫代替她去往敵國和親垦巴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

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