async 函數的返回值到底是什么
async/await 已經成為處理異步操作的標配,它讓我們能夠用看似同步的方式書寫異步代碼,極大地提高了代碼的可讀性和可維護性。我們每天都在寫 await fetch(...)。
但:一個 async 函數,它的返回值究竟是什么?

場景一:返回一個非 Promise 值
這是最常見也最容易產生困惑的情況。我們來看一個最簡單的 async 函數:
async function getNumber() {
return 42; // 返回一個普通的數字
}
const result = getNumber();
console.log(result);如果你運行這段代碼,控制臺輸出的并不會是 42,而是:
Promise { <pending> }很快,這個 Promise 的狀態會變為 fulfilled,并且其值為 42。
背后發生了什么?
當 async 函數的 return 語句返回一個非 Promise 值(如數字、字符串、對象等)時,JavaScript 引擎會自動將其包裝在一個 resolved狀態的 Promise 中。換句話說,上面的代碼在底層等價于:
function getNumber() {
return Promise.resolve(42);
}這就是為什么直接調用 getNumber() 會得到一個 Promise。為了獲取到內部的值 42,我們必須使用 await 或者 .then() 來“解包”:

場景二:返回一個 Promise
如果 async 函數本身就返回一個 Promise,情況會怎樣?JavaScript 引擎會再把它包一層,變成 Promise<Promise<T>> 嗎?
答案是:不會。
async 函數足夠智能,如果它檢測到返回值已經是一個 Promise,它會直接返回這個 Promise,而不會進行額外的包裝。
async function fetchUser() {
// 返回一個顯式的 Promise
return new Promise(resolve => {
setTimeout(() => {
resolve({ name: 'Alice' });
}, 1000);
});
}
const promise = fetchUser();
console.log(promise); // Promise { <pending> }
promise.then(user => {
console.log(user); // 1秒后輸出: { name: 'Alice' }
});這個行為至關重要,它保證了 async 函數的返回值總是一個行為一致的、可 await 的對象,避免了不必要的 Promise 嵌套。
場景三:函數內部拋出錯誤
如果在 async 函數內部 throw 一個錯誤,會發生什么?程序會崩潰嗎?
不一定。async 函數會將拋出的錯誤捕獲,并將其作為 一個 rejected 狀態的 Promise 返回。

這個 rejected Promise 的 reason 就是我們拋出的那個 Error 對象。因此,我們可以用標準的 Promise 錯誤處理方式來捕獲它:
// 使用 try...catch 配合 await
async function handleFailure() {
try {
await willFail();
} catch (error) {
console.error(error.message); // 輸出: Something went wrong!
}
}
handleFailure();
// 或者使用 .catch()
willFail().catch(error => {
console.error(error.message); // 輸出: Something went wrong!
});這種機制將同步代碼中的 try...catch 錯誤處理模型,無縫地融入到了異步流程控制中。
場景四:沒有 return 語句
如果一個 async 函數執行完畢但沒有 return 語句,它的返回值是什么?
和普通函數一樣,沒有 return 語句的函數會隱式地返回 undefined。根據場景一的規則,這個 undefined 會被 async 關鍵字包裝成一個 resolved 狀態的 Promise。
async function doNothing() {
const a = 1 + 1;
// 沒有 return
}
doNothing().then(value => {
console.log(value); // 輸出: undefined
});所以,即使函數什么都不返回,它依然遵循“永遠返回一個 Promise”的黃金法則,只不過這個 Promise 的 resolved 值是 undefined。
async/await 本質上是 Promise 的語法糖。它的設計初衷就是為了讓開發者能夠以更直觀的方式處理異步邏輯。
async 的“包裝”行為和 await 的“解包”行為,兩者相輔相成,構成了這套優雅語法糖的核心。
























