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