現代 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)

注意:

  1. 優先選擇聲明式編程風格

  2. 保持 Promise 鏈的純淨性(避免混合回調)

  3. 善用finally進行狀態清理

  4. 複雜場景優先使用組合器

  5. 瀏覽器兼容性檢測:

if (typeof Promise.allSettled === 'function') {
  // 使用現代特性
} else {
  // 加載polyfill
}

結語

通過合理運用 Promise 鏈式調用、組合器、微任務控制等現代特性,可以在不依賴async/await語法的情況下,構建出高性能、高可維護性的異步系統。這些方案不僅適用於現代瀏覽器環境,在 Serverless、Web Worker 等場景中也展現出色表現。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/9qPZUUPPU_-oT_DI5hrBhA