現代 JavaScript 異步寫法:不依賴 await,構建高性能異步系統
在 ES6 + 時代,JavaScript 異步編程經歷了重大變革。雖然async/await
語法顯著提升了代碼可讀性,但在某些場景下直接操作 Promise 和利用新特性能帶來更精細的控制。
1. Promise 鏈式操作
fetch('https://api.example.com/data')
.then(response => {
if (!response.ok) throw new Error('Network issue')
return response.json()
})
.then(data => {
console.log('Processed data:', data)
return processFurther(data)
})
.then(finalResult => {
saveToDB(finalResult)
})
.catch(error => {
console.error('Error chain:', error)
showUserError(error)
})
.finally(() => {
hideLoadingIndicator()
})
優勢特徵:
-
顯式數據流向
-
統一錯誤處理
-
資源清理保證
2. 高級 Promise 組合器
並行控制
const [user, posts] = await Promise.all([
fetch('/user'),
fetch('/posts')
]);
// 改爲:
Promise.all([
fetch('/user').then(r => r.json()),
fetch('/posts').then(r => r.json())
])
.then(([userData, postsData]) => {
renderDashboard(userData, postsData)
})
.catch(handleGlobalError);
全量結果收集
Promise.allSettled([
fetch('/primary'),
fetch('/fallback')
])
.then(results => {
const successful = results.filter(r => r.status === 'fulfilled')
const errors = results.filter(r => r.status === 'rejected')
// 構建彈性系統
})
競速策略
Promise.any([
fetchFastEndpoint(),
fetchSlowButReliableEndpoint()
])
.then(firstResponse => {
// 獲取首個成功響應
})
.catch(allErrored => {
// 所有請求失敗處理
})
3. 微任務調度優化
function batchUpdates(callback) {
let queue = [];
return function(...args) {
queue.push(args);
queueMicrotask(() => {
if (queue.length > 0) {
const snapshot = queue;
queue = [];
callback(snapshot);
}
});
};
}
4. 事件驅動模式
class AsyncProcessor extends EventTarget {
constructor() {
super();
this.addEventListener('process', this.handleEvent);
}
handleEvent = (e) => {
intensiveCalculation(e.detail)
.then(result => {
this.dispatchEvent(
new CustomEvent('completed', { detail: result })
)
})
}
}
5. 響應式編程模式
function createObservable(fn) {
const subscribers = new Set();
const notify = value => {
queueMicrotask(() => {
subscribers.forEach(sub => sub(value))
})
}
fn({
next: notify,
error: err => notify({ error: err }),
complete: () => notify({ done: true })
});
return {
subscribe: callback => {
subscribers.add(callback)
return () => subscribers.delete(callback)
}
}
}
6. 錯誤處理示例
fetchCriticalData()
.then(validateResponse)
.then(data =>
transformData(data)
.catch(transformationError => {
return getFallbackData()
})
)
.then(finalizeProcessing)
.catch(rootError => {
logToMonitoring(rootError)
emergencyRecovery()
})
關鍵策略:
-
層級化錯誤處理
-
局部恢復機制
-
關鍵錯誤隔離
7. 性能優化
請求競速:Promise.race()
惰性加載:new Promise(resolve => { /* 按需初始化 */ })
緩存策略:
const apiCache = new Map();
function cachedFetch(url) {
if (apiCache.has(url)) {
return Promise.resolve(apiCache.get(url))
}
return fetch(url)
.then(r => r.json())
.then(data => {
apiCache.set(url, data)
return data
})
}
8. 現代瀏覽器 API 整合
navigator.serviceWorker.ready
.then(registration => {
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: VAPID_KEY
})
})
.then(subscription => {
return sendToServer('/register', subscription)
})
.then(confirmSubscription)
注意:
-
優先選擇聲明式編程風格
-
保持 Promise 鏈的純淨性(避免混合回調)
-
善用
finally
進行狀態清理 -
複雜場景優先使用組合器
-
瀏覽器兼容性檢測:
if (typeof Promise.allSettled === 'function') {
// 使用現代特性
} else {
// 加載polyfill
}
結語
通過合理運用 Promise 鏈式調用、組合器、微任務控制等現代特性,可以在不依賴async/await
語法的情況下,構建出高性能、高可維護性的異步系統。這些方案不僅適用於現代瀏覽器環境,在 Serverless、Web Worker 等場景中也展現出色表現。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/9qPZUUPPU_-oT_DI5hrBhA