JavaScript中的同步方法及異步方法示例代碼
1.代碼說明
const saveTem = () => { // 校驗處理 const res = check() if (!res) { return } addTemplateRef.value.openModal() }
這段代碼中,check方法返回的是true和false,是一個普通方法,
openModal也是一個普通方法,沒有返回值,
這段代碼的執(zhí)行順序是依次執(zhí)行的,因為沒有任何異步操作,即使這個方法被async修飾,代碼的執(zhí)行順序也是依次執(zhí)行的
什么是異步操作,可以簡單理解為方法被async修飾,axios及fetch請求及setTimeout方法等。
返回值為promise的方法不一定為異步方法,也就是說異步方法不能通過返回值進(jìn)行判斷
但是異步方法的返回值一定是promise,必須使用await或者.then才能獲取實際返回值
2.async修飾的方法和非async修飾的方法的區(qū)別
1. 返回值不同
async 函數(shù):
總是返回一個 Promise 對象
如果返回非 Promise 值,會自動用 Promise 包裝
如果拋出異常,返回被拒絕(rejected)的 Promise
普通函數(shù):
直接返回 return 語句指定的值
如果沒有 return,返回 undefined
拋出異常會直接中斷執(zhí)行
2. 執(zhí)行方式不同
async 函數(shù):
內(nèi)部可以使用 await 暫停執(zhí)行,使用await后會等待后面的方法執(zhí)行完成,再繼續(xù)后續(xù)的內(nèi)容
不會阻塞主線程
普通函數(shù):
同步執(zhí)行
會阻塞后續(xù)代碼直到執(zhí)行完成
async function asyncFunc() { console.log(1); await new Promise(resolve => setTimeout(resolve, 1000)); console.log(2); } function syncFunc() { console.log(1); setTimeout(() => console.log(2), 1000); console.log(3); } asyncFunc(); // 輸出: 1, 2 (1秒后) syncFunc(); // 輸出: 1, 3, 2 (1秒后)
3. 錯誤處理不同
async 函數(shù):
拋出的錯誤會被捕獲并轉(zhuǎn)換為 rejected Promise
需要使用 try/catch 或 .catch() 捕獲錯誤
普通函數(shù):
錯誤會直接拋出
需要使用 try/catch 捕獲同步錯誤
4. 調(diào)用方式不同
async 函數(shù):
必須用 await 或 .then() 才能獲取結(jié)果
直接調(diào)用會返回 Promise 對象而非實際結(jié)果
普通函數(shù):
直接調(diào)用獲取返回值
5. 適用場景
使用 async 函數(shù)的場景:
需要處理 Promise 鏈?zhǔn)秸{(diào)用,使用之前的.then會導(dǎo)致回調(diào)地獄問題,使用await可以讓多個異步操作按照順序執(zhí)行,使代碼更加整潔
需要順序執(zhí)行多個異步操作
需要更清晰的異步代碼結(jié)構(gòu)
使用普通函數(shù)的場景:
純同步操作
示例
async function getData() { console.log('開始獲取數(shù)據(jù)...'); // 1. 同步執(zhí)行 const result = await fetchData(); // 2. 遇到 await,暫停執(zhí)行并等待 Promise 解決 console.log(result); // 4. Promise 解決后繼續(xù)執(zhí)行 return result; // 5. 返回結(jié)果(包裝在 Promise 中) } // 模擬異步函數(shù) function fetchData() { return new Promise(resolve => { setTimeout(() => resolve('數(shù)據(jù)獲取成功'), 1000); // 3. 1秒后解決 Promise }); } // 調(diào)用示例 getData().then(data => console.log('最終結(jié)果:', data)); // 6. 接收最終結(jié)果
詳細(xì)執(zhí)行流程:
同步階段:
調(diào)用 getData() 函數(shù)
執(zhí)行第一行
console.log
('開始獲取數(shù)據(jù)...')(立即輸出)
遇到 await:
執(zhí)行 fetchData()(返回一個 Promise)
await 會暫停
getData()
函數(shù)的執(zhí)行,將控制權(quán)交回事件循環(huán)此時
getData()
返回一個未解決的 Promise,pending狀態(tài)的promise
異步等待:
fetchData()
中的setTimeout
開始計時(1秒)JavaScript 引擎可以處理其他任務(wù)
Promise 解決:
1秒后,
setTimeout
回調(diào)執(zhí)行,Promise 被解決(resolve)await
接收到解決的值'數(shù)據(jù)獲取成功'
getData()
函數(shù)恢復(fù)執(zhí)行
繼續(xù)執(zhí)行 async 函數(shù):
將解決的值賦給
result
執(zhí)行
console.log(result)
(輸出 "數(shù)據(jù)獲取成功")執(zhí)行
return result
(這里會包裝成一個promise)
處理最終結(jié)果:
.then()
回調(diào)被執(zhí)行,輸出 "最終結(jié)果: 數(shù)據(jù)獲取成功"
關(guān)鍵點說明:
await
會暫停當(dāng)前 async 函數(shù)的執(zhí)行(但不會阻塞主線程)async 函數(shù)在遇到第一個
await
時就會立即返回一個 Promise被暫停的函數(shù)會在 Promise 解決后從暫停點繼續(xù)執(zhí)行
return 的值會自動包裝成 Promise
3.不使用await的場景
場景 1:明確需要 Promise 對象時
const fetchData = async () => { /* ... */ }; // 需要傳遞 Promise 給其他邏輯 const promise = fetchData(); // 不 await,保留 Promise promise.then((data) => { /* ... */ });
場景 2:并行多個異步任務(wù)(用 Promise.all)
const getUser = async () => { /* ... */ }; const getPosts = async () => { /* ... */ }; // 不單獨 await,直接收集 Promises const [user, posts] = await Promise.all([getUser(), getPosts()]);
關(guān)鍵點說明
并行執(zhí)行:
getUser()
和getPosts()
會同時開始執(zhí)行,而不是一個接一個執(zhí)行。Promise.all 的作用:
接收一個 Promise 數(shù)組作為輸入
返回一個新的 Promise,當(dāng)所有輸入的 Promise 都解決(resolve)時,這個新 Promise 才會解決
解決值是一個數(shù)組,包含所有輸入 Promise 的解決值,順序與輸入數(shù)組一致
解構(gòu)賦值:
const [user, posts] = ...
將 Promise.all 返回的數(shù)組解構(gòu)為兩個變量
執(zhí)行流程
調(diào)用
getUser()
和getPosts()
會立即返回兩個 Promise 對象這兩個異步操作會同時開始執(zhí)行(假設(shè)它們不互相依賴)
Promise.all
會等待這兩個 Promise 都完成當(dāng)兩者都完成后,結(jié)果會被解構(gòu)到
user
和posts
變量中
與順序執(zhí)行的對比
如果寫成這樣就是順序執(zhí)行(不推薦):
const user = await getUser(); // 等待這個完成 const posts = await getPosts(); // 然后才開始這個
而使用 Promise.all
的方式總耗時大約等于較慢的那個操作的時間,而不是兩者時間相加。
注意事項
如果其中一個 Promise 被拒絕(reject),整個
Promise.all
會立即拒絕適合用于彼此獨立的異步操作
如果操作之間有依賴關(guān)系,可能需要順序執(zhí)行
4.總結(jié)
方法中如果沒有異步方法,按照順序依次執(zhí)行
如果有異步方法,沒有使用await或者.then,不會依次執(zhí)行,會先執(zhí)行異步方法后面的方法,再執(zhí)行異步方法
如果需要控制方法內(nèi),異步方法的順序,可以使用await或者.then,需要注意如果要使用await,則方法必須被async修飾
使用async修飾的方法,返回值為promise,需要使用await或者.then獲取返回值
返回值為promise不一定是異步方法,異步方法的返回值一定是promise
常見的異步方法為async修飾的方法,setimeout方法,axios方法,fetch方法
到此這篇關(guān)于JavaScript中的同步方法及異步方法的文章就介紹到這了,更多相關(guān)js同步方法及異步方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序?qū)崿F(xiàn)單個卡片左滑顯示按鈕并防止上下滑動干擾功能
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)單個卡片左滑顯示按鈕并防止上下滑動干擾功能,利用小程序事件處理的api,分別讀取觸摸開始,觸摸移動時,觸摸結(jié)束的X/Y坐標(biāo),根據(jù)差值來改變整個卡片的位置,具體實例代碼跟隨小編一起看看吧2019-12-12js實現(xiàn)在文本框光標(biāo)處添加字符的方法介紹
在開發(fā)應(yīng)用中,經(jīng)常會遇到一些技術(shù)上的問題,比如:怎樣讓js在文本框光標(biāo)處添加字符,本文將以此問題進(jìn)行詳細(xì)介紹,需要了解的朋友可以參考下2012-11-11javascript實現(xiàn)頁面刷新時自動清空表單并選中的方法
這篇文章主要介紹了javascript實現(xiàn)頁面刷新時自動清空表單并選中的方法,涉及javascript中reset與focus方法的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07關(guān)于Javascript 對象(object)的prototype
Javascript中的每個對象(object)都會有 prototype,下面為大家介紹下其具體的應(yīng)用2014-05-05