本篇內容主要講解“JavaScript中的async函數(shù)怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JavaScript中的async函數(shù)怎么使用”吧!
成都創(chuàng)新互聯(lián)公司自2013年創(chuàng)立以來,先為唐山等服務建站,唐山等地企業(yè),進行企業(yè)商務咨詢服務。為唐山企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
async函數(shù)的返回值為 promise 對象,promise對象的結果由async函數(shù)執(zhí)行的返回值決定。async函數(shù)能使得異步操作變得更加方便,簡而言之就是 Generator 的語法糖。
定義async函數(shù),特點是即便函數(shù)內部返回結果不是promise對象,調用函數(shù)其最后的返回結果依然是promise對象,代碼如下:
如果返回的結果不是 Promise 對象的情況下:
<script>
async function fn(){
// 返回的結果是字符串
// return '123'
// // 返回的結果是undefined
// return;
// 返回的結果是拋出一個異常
throw new 'error'
}
const result = fn()
console.log(result);
</script>
如果返回的結果是 Promise 對象時,我們正常使用 then 方法即可,如下:
<script>
async function fn(){
return new Promise((resolve,reject)=>{
// resolve('成功的數(shù)據(jù)')
reject('失敗的數(shù)據(jù)')
})
}
const result = fn()
// 調用 then 方法
result.then((value)=>{
console.log(value);
},(reason)=>{
console.log(reason); // 打印失敗的數(shù)據(jù)
})
</script>
通過上文的對 async 介紹,感覺其功能有點雞肋,其實恰恰不是,而是 async 需要搭配 await 一起使用才能達到語法糖的效果。
await的特點:
await必須寫在 async 函數(shù)中
await右側的表達式一般為 promise 對象
await返回的是 promise 成功的值
await的 promise 失敗了,就會拋出異常,需要通過 try...catch捕獲處理
說白了:await就相當于 then 方法的第一個回調函數(shù),只返回成功的值,失敗的值需要 try...catch來捕獲。
async函數(shù)內部拋出錯誤,會導致返回的 Promise 對象變?yōu)閞eject狀態(tài)。拋出的錯誤對象會被catch方法回調函數(shù)接收到。
<script>
const p = new Promise((resolve,reject)=>{
// resolve('用戶數(shù)據(jù)')
reject('用戶加載數(shù)據(jù)失敗了')
})
async function fn(){
// 為防止promise是失敗的狀態(tài),加上try...catch進行異常捕獲
try {
// await 返回的結果就是 promise 返回成功的值
let result = await p
console.log(result);
} catch (error) {
console.log(error);//因為是失敗的狀態(tài),所以打印:用戶加載數(shù)據(jù)失敗了
}
}
fn()
</script>
總結:
(1)await命令后面的Promise對象,運行結果可能是rejected,所以最好把await命令放在try...catch代碼塊中。
(2)如果有多個await命令后面的異步操作,如果不存在繼發(fā)關系,最好讓它們同時觸發(fā)。
比如:await Promise.all([a(), b()]),這里簡單提一下
(3)await命令只能用在async函數(shù)之中,如果用在普通函數(shù),就會報錯。
(4)(理解一下async的運行原理) async 函數(shù)可以保留運行堆棧,普通函數(shù)內部運行一個異步任務時,如果異步任務運行結束普通函數(shù)可能早就運行完了,異步任務的上下文環(huán)境已經(jīng)消失了,如果異步任務報錯,錯誤堆棧將不包括普通函數(shù);而async函數(shù)內部的異步任務運行時,async函數(shù)是暫停執(zhí)行的,所以一旦async函數(shù)內部的異步任務運行報錯,錯誤堆棧將包括async函數(shù)。
// 函數(shù)聲明
async function foo() {}
// 函數(shù)表達式
const foo = async function () {};
// 對象的方法
let obj = { async foo() {} };
obj.foo().then(...)
// Class 的方法
class Storage {
constructor() {
this.cachePromise = caches.open('avatars');
}
async getAvatar(name) {
const cache = await this.cachePromise;
return cache.match(`/avatars/${name}.jpg`);
}
}
const storage = new Storage();
storage.getAvatar('jake').then(…);
// 箭頭函數(shù)
const foo = async () => {};
和之前講解的 promise 讀取文件內容 一樣,我們也可以使用async進行文件的讀取,代碼如下:
// 1.引入 fs 模塊
const fs = require('fs')
// 2.讀取文件
function index(){
return new Promise((resolve,reject)=>{
fs.readFile('./index.md',(err,data)=>{
// 如果失敗
if(err) reject(err)
// 如果成功
resolve(data)
})
})
}
function index1(){
return new Promise((resolve,reject)=>{
fs.readFile('./index1.md',(err,data)=>{
// 如果失敗
if(err) reject(err)
// 如果成功
resolve(data)
})
})
}
function index2(){
return new Promise((resolve,reject)=>{
fs.readFile('./index2.md',(err,data)=>{
// 如果失敗
if(err) reject(err)
// 如果成功
resolve(data)
})
})
}
// 3.聲明一個 async 函數(shù)
async function fn(){
let i = await index()
let i1 = await index1()
let i2 = await index2()
console.log(i.toString());
console.log(i1.toString());
console.log(i2.toString());
}
fn()

和之前講解 promise發(fā)送ajax請求 一樣,我們也可以使用async進行發(fā)送ajax請求,代碼如下:
<script>
// 發(fā)送 AJAX請求,返回的結果是 Promise 對象
function sendAjax(url){
return new Promise((resolve,reject)=>{
// 創(chuàng)建對象
const x = new XMLHttpRequest()
// 初始化
x.open('GET',url)
// 發(fā)送
x.send()
// 事件綁定
x.onreadystatechange = function(){
if(x.readyState === 4){
if(x.status >= 200 && x.status < 300){
// 如果響應成功
resolve(x.response)
// 如果響應失敗
reject(x.status)
}
}
}
})
}
// promise then 方法測試
// const result = sendAjax("https://ai.baidu.com/").then(value=>{
// console.log(value);
// },reason=>{})
// async 與 await 測試
async function fn(){
// 發(fā)送 AJAX 請求
let result = await sendAjax("https://ai.baidu.com/")
console.log(result);
}
fn()
</script>

我們發(fā)現(xiàn) async與await之間的關系 和 Generator與yield之間的關系十分類似,不熟悉Generator的朋友可以看一下我之前的文章:生成器講解 ;一比較就發(fā)現(xiàn): async函數(shù)就是將 Generator 函數(shù)的星號(*)替換成async,將yield替換成await。代碼比較如下:
<script>
// Generator 函數(shù)
function * person() {
console.log('hello world');
yield '第一分隔線'
console.log('hello world 1');
yield '第二分隔線'
console.log('hello world 2');
yield '第三分隔線'
}
let iterator = person()
// console.log(iterator); 打印的就是一個迭代器對象,里面有一個 next() 方法,我們借助next方法讓它運行
iterator.next()
iterator.next()
iterator.next()
// async函數(shù)
const person1 = async function (){
console.log('hello world');
await '第一分隔線'
console.log('hello world 1');
await '第二分隔線'
console.log('hello world 2');
await '第三分隔線'
}
person1()
</script>

async函數(shù)的實現(xiàn)原理就是將 Generator 函數(shù)和自動執(zhí)行器包裝在一個函數(shù)里。
<script>
async function fn(args) {}
// 等同于
function fn(args) {
// spawn函數(shù)就是自動執(zhí)行器
return spawn(function* () {});
}
</script>
我們可以分析一下 Generator 和 async 代碼的書寫特點和風格:
<script>
// Generator 函數(shù)
function Generator(a, b) {
return spawn(function*() {
let r = null;
try {
for(let k of b) {
r = yield k(a);
}
} catch(e) {
/* 忽略錯誤,繼續(xù)執(zhí)行 */
}
return r;
});
}
// async 函數(shù)
async function async(a, b) {
let r = null;
try {
for(let k of b) {
r = await k(a);
}
} catch(e) {
/* 忽略錯誤,繼續(xù)執(zhí)行 */
}
return r;
}
</script>
所以 async 函數(shù)的實現(xiàn)符合語義也很簡潔,不用寫Generator的自動執(zhí)行器,改在語言底層提供,因此代碼量少。
從上文代碼我們可以總結以下幾點:
(1)Generator函數(shù)執(zhí)行需要借助執(zhí)行器,而async函數(shù)自帶執(zhí)行器,即async不需要像生成器一樣需要借助 next 方法才能執(zhí)行,而是會自動執(zhí)行。
(2)相比于生成器函數(shù),我們可以看到 async 函數(shù)的語義更加清晰
(3)上面就說了,async函數(shù)可以接受Promise或者其他原始類型,而生成器函數(shù)yield命令后面只能是Promise對象或者Thunk函數(shù)。
(4)async函數(shù)返回值只能是Promise對象,而生成器函數(shù)返回值是 Iterator 對象
到此,相信大家對“JavaScript中的async函數(shù)怎么使用”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
網(wǎng)站名稱:JavaScript中的async函數(shù)怎么使用
網(wǎng)頁路徑:http://chinadenli.net/article30/ipdhso.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供關鍵詞優(yōu)化、外貿(mào)網(wǎng)站建設、動態(tài)網(wǎng)站、商城網(wǎng)站、軟件開發(fā)、搜索引擎優(yōu)化
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)