回調函數由於涉及的內容多而雜,而且在項目中也不怎麼使用,因此在這裏就先不說了,node
本章重點講解一下 Promise
、generator + co
、async/await
git
由於裏面內容會有點多,而且還有好多代碼示例。因此須要靜下心慢慢看,相信看完以後,你確定會對這三種方法涉及的異步問題的理解更上一層樓面試
若是想要大體瞭解一下的話,能夠看看個人這篇文章《JS中的異步解決方案》npm
我們先說Promise
,而後慢慢涉及到其餘,按部就班(其實這是JS處理異步的一個發展流程)數組
開始吧!!!promise
Promise
Promise簡單的說就是一個容器,裏面保存着某個將來纔會結束的時間(一般是一個異步操做)的結果。從語法上說,Promise就是一個對象,從它能夠獲取異步操做的消息。Promise提供統一的API,各類異步操做均可以用一樣的方法處理。bash
如何理解:異步
4大術語
必定要結合異步操做來理解
既然是異步,這個操做須要有個等待的過程,從操做開始,到獲取結果,有一個過程的async
- 解決(fulfill)指一個 promise 成功時進行的一系列操做,如狀態的改變、回調的執行。雖然規範中用 fulfill 來表示解決,但在後世的 promise 實現多以 resolve 來指代之
- 拒絕(reject)指一個 promise 失敗時進行的一系列操做
- 終值(eventual value)所謂終值,指的是 promise 被解決時傳遞給解決回調的值,因爲 promise 有一次性的特徵,所以當這個值被傳遞時,標誌着 promise 等待態的結束,故稱之終值,有時也直接簡稱爲值(value)
- 據因(reason)也就是拒絕緣由,指在 promise 被拒絕時傳遞給拒絕回調的值
3種狀態
在異步操做中,當操做發出時,須要處於等待狀態
當操做完成時,就有相應的結果,結果有兩種:編輯器
- 成功了
- 失敗了
一共是3種狀態,以下:
- 等待態(Pending (也叫進行態)
- 執行態(Fulfilled)(也叫成功態)
- 拒絕態(Rejected) (也叫失敗態)
針對每一種狀態,有一些規範:
等待態(Pending)
處於等待態時,promise 需知足如下條件:
- 能夠遷移至執行態或拒絕態
執行態(Fulfilled)
處於執行態時,promise 需知足如下條件:
- 不能遷移至其餘任何狀態
- 必須擁有一個不可變的終值
拒絕態(Rejected)
處於拒絕態時,promise 需知足如下條件:
- 不能遷移至其餘任何狀態
- 必須擁有一個不可變的據因
2種事件
針對3種狀態,只有以下兩種轉換方向:
- pending –> fulfilled
- pendeing –> rejected
在狀態轉換的時候,就會觸發事件:
- 若是是pending –> fulfiied,就會觸發onFulFilled事件
- 若是是pendeing –> rejected,就會觸發onRejected事件
在調用resolve方法或者reject方法的時候,就必定會觸發事件
須要註冊onFulFilled事件 和 onRejected事件
針對事件的註冊,Promise對象提供了then方法,以下:
promise.then(onFulFilled,onRejected)
針對 onFulFilled,會自動提供一個參數,做爲終值(value)
針對 onRejected,會自動提供一個參數,做爲據因(reason)
1個對象
promise
注:只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘的操做都沒法改變這個狀態
當咱們建立 promise
時,會默認的處於 Pending
狀態,而且在建立的時候,promise
中必定要有一個執行器,而且這個執行器會當即執行
// ()=>{} 叫執行器,會當即執行
let p = new Promise(()=>{ })
// 剛建立的Promise默認處理Pending狀態
console.log(p) // Promise { <pending> }
複製代碼
在 promise
的執行器中須要傳入兩個參數,分別是 resolve
和 reject
,在內部調用時,就分別表明狀態由 pending=>fulfilled(成功) pending=>rejected(失敗)
而且一旦 promise
狀態發生變化以後,以後狀態就不會再變了。好比:調用 resolve
以後,狀態就變爲 fulfilled
,以後再調用 reject
,狀態也不會變化
let p = new Promise((resolve,reject)=>{
resolve("有錢了....") // 如今promise就處理成功態
})
console.log(p) // Promise { '有錢了....' }
//失敗態就不演示了
複製代碼
切記狀態發生變化以後,以後狀態就不會再變了
// 一個promise的狀態只能從等待到成功,或從等待到失敗
let p = new Promise((resolve,reject)=>{
resolve("有錢了...") // 成功了....
reject("沒錢了...") // 失敗了....
})
p.then(()=>{
console.log("成功了....")
},()=>{
console.log("失敗了...")
})
//只能輸出 成功了...
複製代碼
then
方法上面代碼已經看到了,在使用時能夠經過promise
對象的內置方法then
進行調用,then
有兩個函數參數,分別表示promise
對象中調用resolve
和reject
時執行的函數
let p = new Promise((resolve,reject)=>{
// resolve("有錢了...") // 成功了....
reject("沒錢了...") //失敗了....
})
// 在then方法中,有兩個參數
// 第一個參數表示從等待狀到成功態,會調用第1個參數
// 第二個參數表示從等待狀到失敗態,會調用第2個參數
p.then(()=>{
console.log("有錢了....")
},()=>{
console.log("沒錢了...")
})
//輸出結果 沒錢了...
複製代碼
在執行完後,成功確定有一個成功的結果 失敗確定有一個失敗的緣由,那麼如何獲得成功的結果 ? 如何獲得失敗緣由呢?
let p = new Promise((resolve,reject)=>{
// 調用reolve時,能夠把成功的結果傳遞下去
// resolve("有錢了...") // 成功了...
// 調用reject時,能夠把失敗的緣由傳遞下去
reject("沒錢了...") // 失敗了....
})
p.then((suc)=>{
console.log(suc)
},(err)=>{
console.log(err)
})
//輸出結果 沒錢了...
複製代碼
當咱們在執行失敗處理時,也能夠用 throw
,就是拋出一個錯誤對象,也是失敗的
以下:
let p = new Promise((resolve,reject)=>{
// throw 一個錯誤對象 也是失敗的
throw new Error("沒錢了...")
})
p.then((suc)=>{
console.log(suc)
},(err)=>{
console.log(err)
})
複製代碼
throw
的定義:throw
語句用來拋出一個用戶自定義的異常。當前函數的執行將被中止(throw
以後的語句將不會執行),而且控制將被傳遞到調用堆棧中的第一個catch
塊。若是調用者函數中沒有catch
塊,程序將會終止。
//嘗試一下
function getRectArea(width, height) {
if (isNaN(width) || isNaN(height)) {
throw "Parameter is not a number!";
}
}
try {
getRectArea(3, 'A');
}
catch(e) {
console.log(e);
// expected output: "Parameter is not a number!"
}
複製代碼
promise自己是同步的
// promise自己是同步的
console.log("start")
let p = new Promise(()=>{
console.log("哈哈") // 哈哈
})
console.log("end")
//輸出順序 start 哈哈 end
複製代碼
而且在執行器的內部也是能夠寫異步代碼的
那麼then
中的方法何時調用呢?
只有當調用resolve
,reject
時纔會去執行then
中的方法**
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("setTimeout")
// resolve("有錢了...")
reject("沒錢了...")
},1000)
})
p.then((suc)=>{
console.log(suc) // 有錢了...
},(err)=>{
console.log(err) // 沒錢了...
})
複製代碼
首先咱們在目錄下面建兩個文件,分別是:name.txt
和 age.txt
name.txt
文件裏寫了一個 age.txt
age.txt
文件裏寫了一個 666
下面就以讀取文件爲例,來演示鏈式調用(須要瞭解一點node基礎)
當你讀取文件的時候,若是你用的是 vscode 編輯器,裏面會有一個小bug,用相對路徑可能會出錯,因此最好使用絕對路徑
讀取文件:
let fs = require("fs")
let path = require("path")
let filename = path.join(__dirname,"name.txt")
fs.readFile(filename,"utf8",(err,data)=>{
if(err){
console.log(err)
}
fs.readFile(path.join(__dirname,data),"utf8",(err,data)=>{
if(err){
console.log(err)
}
console.log(data)
})
})
//輸出結果 666
複製代碼
若是用這種方法,就會出現 回調地獄 ,很難受,因此通常不用
在讀取文件時,咱們能夠專門 封裝一個函數 ,功能就是讀取一個文件的內容
let fs = require("fs")
// 封裝一個函數,函數的功能是讀取一個文件的內容
// rest參數(下去本身瞭解一下,就是能夠獲取到傳過來的全部內容)
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
//讀文件
readFile("./name.txt","utf8").then(data=>{
console.log(data)
},err=>{
console.log(err)
})
//輸出結果 age.txt
複製代碼
若是文件不存在,會走第二個函數
let fs = require("fs")
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
// 若是name1不存在,走then的第2個函數
readFile("./name1.txt","utf8").then(data=>{
console.log(data)
},err=>{
console.log(err)
})
//報錯 no such file or directory
複製代碼
那麼若是咱們想要讀取age.txt
裏面的內容呢?
咱們能夠這麼寫:
let fs = require("fs")
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
readFile("./name.txt","utf8").then(data=>{
// console.log(data) // age.txt
readFile(data,"utf8").then(data=>{
console.log(data) // 666
},err=>{
console.log(err)
})
},err=>{
console.log(err)
})
//輸出結果 666
複製代碼
這樣寫就能夠獲取到age.txt
文件裏面的內容,可是呢,這樣寫又回到了 回調地獄 ,不是說這種方法不行,而是不夠優雅
使用 鏈式調用
在promise
中能夠鏈式調用 就是 .then
以後,還能夠 .then
,你能夠無數次的 .then
.then
以後又返回了一個新的 promise
,就是.then
的函數參數中會默認返回promise
對象,因此當你碰到.then
連續調用的時候,你就能夠把前面的全部代碼當成一個promise
let fs = require("fs")
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
readFile("./name.txt","utf8").then(data=>{
// console.log(data) // age.txt
return false;
},err=>{
console.log(err)
}).then(data=>{ // 這裏面的data是上一個then中的第一個函數的返回值,這個.then前面的一坨代碼就能夠當成一個promise
console.log(data) // false
},err=>{
})
複製代碼
若是沒有這個文件,則返回錯誤信息
let fs = require("fs")
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
readFile("./name1.txt","utf8").then(data=>{
return data;
},err=>{
return err;
// console.log(err)
}).then(data=>{
console.log(data)
},err=>{
console.log(err)
})
//輸出結果 no such file or directory
複製代碼
可是若是咱們返回一個promise
呢?
那麼這個promise
會執行,而且會採用他的狀態
let fs = require("fs")
function readFile(...args){
return new Promise((resolve,reject)=>{
fs.readFile(...args,function(err,data){
if(err) reject(err)
resolve(data)
})
});
}
readFile("./name.txt","utf8").then(data=>{
return data;
},err=>{
return err;
// console.log(err)
}).then(data=>{
// console.log(data)
return new Promise((resolve,reject)=>{ //返回一個promise
reject("不OK") //下面的.then採用這個狀態(失敗態)
})
},err=>{}).then(data=>{
console.log(data)
},err=>{
console.log(err) // 不OK
})
//輸出結果 不OK
複製代碼
因此若是返回的是一個promise
,那麼這個promise
會執行,而且會採用它的狀態
小總結:
若是在上一個then
的第一個函數中,返回一個普通值,那麼不管你是在第1個函數中返回,仍是在第2個函數中返回,都會做爲下一個then的成功的結果,若是不返回,undefined
就做爲下一個then的成功的結果
若是返回的是一個promise
,會做爲下一個then
的promise
對象,data err去promise
對象中去取,也就是說,前一個then
的返回值,會做爲後一個then
的參數
再給兩個小例子,本身看一下:
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("hello")
},1000)
})
p.then(data=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("world")
},1000)
})
}).then(data=>{
console.log(data)
},err=>{
})
//輸出結果 world
複製代碼
let p = new Promise((resolve,reject)=>{
resolve("hello")
})
let p1 = p.then(data=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("不OK")
},1000)
})
})
p1.then(data=>{
console.log(data)
},err=>{
console.log(err)
})
//輸出結果 不OK
複製代碼
接下來講一個小問題,鏈式調用中的 循環引用
有的人不喜歡把前面的一大堆代碼後面加.then
,因此就用了下面的一種寫法(有可能會出現 循環引用):
let p = new Promise((resolve,reject)=>{
resolve("hello")
})
let p1 = p.then(data=>{
return p1 //循環引用 報錯 p1在等p1的狀態改變,也就是我在等我吃飯,顯然是不行的
})
p1.then(data=>{
console.log(data)
},err=>{
console.log("-----",err) //可執行,而後報錯
})
複製代碼
若是咱們把狀態肯定住,那就能夠了
let p = new Promise((resolve,reject)=>{
resolve("hello")
})
let p1 = p.then(data=>{
// return 123 至關於把等待態改變成成功態
return 123
})
p1.then(data=>{
console.log(data) // 123
},err=>{
console.log("-----",err)
})
//輸出 123
複製代碼
固然改變成失敗態也能夠
let p = new Promise((resolve,reject)=>{
resolve("hello")
})
let p1 = p.then(data=>{
// return new Error("不OK") 把等待態變成失敗態
return new Error("不OK")
})
p1.then(data=>{
console.log(data)
},err=>{
console.log(err) // Error: 不OK
})
複製代碼
看一個問題
let p = new Promise((resolve,reject)=>{
resolve("hello")
})
let p1 = p.then(data=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("666")
},1000)
}))
},1000)
})
})
// data是promise 仍是666
p1.then(data=>{
console.log(data)
},err=>{
console.log(err)
})
複製代碼
按理說,data打印出來的是一個promise
,就是上面resolve
裏面的一堆代碼
然而並非,promise
會 進行遞歸解析.到最後上面代碼會打印出來 666
若是在resolve
或reject
中又是一個promise
,那麼就會遞歸解析(不管有多少個promise
)
let p = new Promise((resolve, reject) => {
resolve("hello")
})
let p1 = p.then(data => {
return new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve("666")
}))
}))
}))
}))
}))
})
})
p1.then(data => {
console.log(data)
}, err => {
console.log(err)
})
//打印結果 666
複製代碼
catch
方法catch
方法,用於註冊 onRejected
回調catch
實際上是then
的簡寫,then(null,callback)
catch
就是.then
的語法糖
若是.then
中有第2個函數,在這個.then
後面又有catch
,若是到失敗態,那麼會走.then
的第2個函數
let p = new Promise((resolve,reject)=>{
reject("不OK")
})
p.then(data=>{
},err=>{
console.log("1",err)
}).catch(err=>{
console.log("2",err)
})
//輸出結果 1 不OK
複製代碼
若是.then
中沒有第2個函數,在這個.then
後面又有catch
,若是到失敗態,那麼會走catch
let p = new Promise((resolve,reject)=>{
reject("不OK")
})
p.then(data=>{
}).catch(err=>{
console.log("2",err)
})
//輸出結果 2 不OK
複製代碼
在.then
第二個函數中,return err
這個 err 它是 return 到了下一個.then
的第一個函數中
let p = new Promise((resolve,reject)=>{
reject("不OK")
})
p.then(data=>{
},err=>{
// 在這裏它並無reutrn到err中,它reutrn到第一個參數中
return err
}).then(data=>{
console.log("data----",data)
},err=>{
console.log("err----",err)
})
//輸出結果 data---- 不OK
複製代碼
因此最終:
一個promise
中,通常在then
中只有一個函數,在then
後面有一個catch
,通常使用then
來獲取data
,在catch
中獲取err
let p = new Promise((resolve,reject)=>{
resolve("OK")
})
p.then(data=>{
console.log(data)
}).catch(err=>{
console.log(err)
})
複製代碼
在Pomise
類上面,提供了幾個靜態方法:
resolve
reject
finally
all
race
resolve
Promise.resolve("有錢了...").then(data=>{
console.log(data) // 有錢了...
})
複製代碼
等價於下面這種寫法:
let p = new Promise((resolve,reject)=>{
resolve("有錢了...")
})
p.then(data=>{
console.log(data)
})
複製代碼
reject
Promise.reject("沒錢了...").catch(data=>{
console.log(data) // 沒錢了...
})
複製代碼
finally
無論轉成成功態仍是失敗態,都會調用finally
這個方法
Promise.resolve("有錢").then(data=>{
console.log(data)
}).finally(()=>{
console.log("開心...")
})
//打印結果 有錢 開心...
複製代碼
Promise.reject("沒錢").catch(data=>{
console.log(data)
}).finally(()=>{
console.log("不開心...")
})
//打印結果 沒錢 不開心...
複製代碼
all
all
表示[ ]中的promise
都成功了,才能獲得最終的值
注意裏面是一個數組 讀取name.txt
和age.txt
中的內容
let fs = require("fs").promises;
// all表示[]中的promise都成功了,才能獲得最終的值
Promise.all([fs.readFile("./name.txt","utf-8"),fs.readFile("./age.txt","utf-8")]).then(data=>{
console.log(data) // [ 'age.txt', '666' ]
})
//打印結果 [ 'age.txt', '666' ]
複製代碼
若是有一個不成功,那麼就不行
let fs = require("fs").promises;
Promise.all([fs.readFile("./name1.txt","utf-8"),fs.readFile("./age.txt","utf-8")]).then(data=>{
console.log(data)
})
//這個是不行的
複製代碼
race
顧名思義,race
就是賽跑的意思,意思就是說,Promise.race([p1, p2, p3])裏面哪一個結果得到的快,就返回那個結果,無論結果自己是成功狀態仍是失敗狀態。
let fs = require("fs").promises;
Promise.race([fs.readFile("./name.txt","utf-8"),fs.readFile("./age.txt","utf-8")]).then(data=>{
console.log(data) // age.txt
})
複製代碼
改變文件裏面的內容,多嘗試幾回
generator + co
我很佩服你能看到這裏,厲害
先說 生成器 和 迭代器
生成器能夠生成迭代器,可讓程序中斷,不會把 { } 中的代碼所有執行
用法:在function
和本身聲名的名稱之間加一個 * 號,裏面用yield
產出數據,而後調用生成器生成迭代器
function * read(){
yield 1; // 只有產出,並不執行
}
//調用生成器 生成 迭代器 it就是迭代器
let it = read()
複製代碼
生成器能夠產出不少值,迭代器只能next一下,拿一個值,next一下,拿一個值
function * read(){
yield 1;
}
let it = read()
console.log(it.next()) // { value: 1, done: false }
console.log(it.next()) // { value: undefined, done: true }
複製代碼
function * read(){
yield 1;
yield 2;
yield 3;
}
// 調用read() 返回值是迭代器
let it = read()
console.log(it.next()) // { value: 1, done: false }
console.log(it.next()) // { value: 2, done: false }
console.log(it.next()) // { value: 3, done: false }
console.log(it.next()) // { value: undefined, done: true }
複製代碼
若是 next 中有參數的話,那麼他會把這個參數傳給上一個生成器聲明的變量裏
因此第一個 next 中的參數沒有任何意義,咱們通常不寫
function * read(){
let a = yield 1;
console.log(a) // 9
let b = yield 2;
console.log(b) // 10
let c = yield 3;
console.log(c) // 11
}
let it = read()
console.log(it.next()) // { value: 1, done: false }
console.log(it.next(9)) // { value: 2, done: false }
console.log(it.next(10)) // { value: 3, done: false }
console.log(it.next(11)) // { value: undefined, done: true }
複製代碼
接下來用這個實現咱們的讀文件操做,哈哈,是否是很噁心
讀取name.txt
文件
const fs = require("fs").promises;
// 生成器
function * read(){
yield fs.readFile("./name.txt","utf-8")
}
// 迭代器
let it = read()
// console.log(it.next()) // { value: Promise { <pending> }, done: false }
it.next().value.then(data=>{ //由於是一個對象,因此直接.value
console.log(data)
})
//輸出結果 age.txt
複製代碼
而後讀取age.txt
文件
const fs = require("fs").promises;
function * read(){
let concent = yield fs.readFile("./name.txt","utf-8")
yield fs.readFile(concent,"utf-8")
}
let it = read()
it.next().value.then(data=>{
// console.log(data)
// console.log(it.next(data)) // { value: Promise { <pending> }, done: false }
it.next(data).value.then(data=>{
console.log(data)
})
})
//輸出結果 666
複製代碼
也能夠這樣
const fs = require("fs").promises;
function * read(){
let concent = yield fs.readFile("./name.txt","utf-8")
let age = yield fs.readFile(concent,"utf-8")
return age
}
let it = read()
it.next().value.then(data=>{
it.next(data).value.then(data=>{
let r = it.next(data)
console.log(r) // { value: '666', done: true }
})
})
複製代碼
是否是感受又陷入了 回調地獄
那麼就用 co 吧
安裝co npm i co
用上來:
const fs = require("fs").promises;
function * read(){
let concent = yield fs.readFile("./name.txt","utf-8")
let age = yield fs.readFile(concent,"utf-8")
return age
}
let co = require("co")
co(read()).then(data=>{
console.log(data) //
})
//輸出結果 666
複製代碼
是否是簡單多了,爽不爽
co
庫能夠實現自動迭代
既然是自動執行,那麼promise
的executor
中先執行一次it.next()
方法,返回value
和done
;value
是一個pending
的Promise
;若是done=false
,說明尚未走完,繼續在value.then
的成功回調中執行下一次next
,即調用read
方法;直到done
爲true
,走完全部代碼,調用resolve
;中間有任何一次next
異常,直接調用reject
,中止迭代
總結:
function
關鍵字與函數名之間有一個星號yield
語句,定義不一樣的內部狀態yield
會將函數分割成好多個部分,每產出一次,就暫停一次Genenrator
是一個生成器,調用Genenrator
函數,不會當即執行函數體,只是建立了一個迭代器對象,如上例中的it
就是調用read
這個Generator
函數獲得的一個迭代器next
方法,調用一次就會繼續向下執行,直到遇到下一個yield
或return
next()
方法能夠帶一個參數,該參數會被當作上一條yield
語句的返回值,並賦值給yield
前面等號前的變量yield
,就會返回一個{value:xxx,done:bool}
的對象,而後暫停,返回的value
就是跟在yield
後面的返回值,done
表示這個generator
是否已經執行結束了return
時,return
後的值就是value
值,done
此時就是true
return
,就是隱含的return undefined
co
庫,能夠自動的將generator
迭代co
執行會返回一個promise
,用then
註冊成功/失敗回調co
將迭代器it
做爲參數,這裏每調用一次read
,就執行一次next
async/await
被稱爲 異步解決 的終極方案
async、await是什麼?
async
顧名思義是「異步」的意思,async
用於聲明一個函數是異步的。
而await
從字面意思上是「等待」的意思,就是用於等待異步完成。通俗來講,就是await
在這裏等待promise
返回結果了,再繼續執行。而且await
只能在async
函數中使用
一般async
、await
都是跟隨Promise
一塊兒使用的。
爲何這麼說呢?由於 async
返回的都是一個Promise
對象,同時async
適用於任何類型的函數上。這樣await
獲得的就是一個Promise
對象(若是不是Promise
對象的話那async
返回的是什麼 就是什麼);
注: await
不只僅用於等 Promise
對象,它能夠等任意表達式的結果,因此,await
後面實際是能夠接普通函數調用或者直接量的(不演示了)
緊跟着上面的代碼,再寫一段
const fs = require("fs").promises;
async function read(){
let concent = await fs.readFile("./name.txt","utf-8")
let age = await fs.readFile(concent,"utf-8")
return age
}
read().then(data=>{
console.log(data) // 666
})
複製代碼
是否是比上面的寫法還爽呢?
await
命令後面的 Promise
對象,運行結果多是 rejected
,因此最好把 await
命令放在 try...catch
代碼塊中
以下:
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
// 另外一種寫法
async function myFunction() {
await somethingThatReturnsAPromise().catch(function (err){
console.log(err);
});
}
複製代碼
總結:
async:
async
函數會返回一個Promise
對象async
函數中是return
一個值,這個值就是Promise
對象中resolve
的值async
函數中是throw
一個值,這個值就是Promise
對象中reject
的值await:
await
只能在async
函數中使用await
後面要跟一個promise
對象await
等promise
返回結果後,在繼續執行這三種方法都是用來解決異步的,很很很重要
一般到公司面試的時候,面試官都會問到:
那麼看完本章內容就派上大用場了哦!
好了本章就先到此結束了,咱們下期再見