
- Javascript 基礎教程
- Javascript - 首頁
- JavaScript - 路線圖
- JavaScript - 概述
- JavaScript - 特性
- JavaScript - 啟用
- JavaScript - 位置
- JavaScript - 語法
- JavaScript - Hello World
- JavaScript - Console.log()
- JavaScript - 註釋
- JavaScript - 變數
- JavaScript - let 語句
- JavaScript - 常量
- JavaScript - 資料型別
- JavaScript - 型別轉換
- JavaScript - 嚴格模式
- JavaScript - 保留關鍵字
- JavaScript 運算子
- JavaScript - 運算子
- JavaScript - 算術運算子
- JavaScript - 比較運算子
- JavaScript - 邏輯運算子
- JavaScript - 位運算子
- JavaScript - 賦值運算子
- JavaScript - 條件運算子
- JavaScript - typeof 運算子
- JavaScript - 空值合併運算子
- JavaScript - delete 運算子
- JavaScript - 逗號運算子
- JavaScript - 分組運算子
- JavaScript - yield 運算子
- JavaScript - 展開運算子
- JavaScript - 指數運算子
- JavaScript - 運算子優先順序
- JavaScript 控制流
- JavaScript - if...else
- JavaScript - while 迴圈
- JavaScript - for 迴圈
- JavaScript - for...in
- Javascript - for...of
- JavaScript - 迴圈控制
- JavaScript - break 語句
- JavaScript - continue 語句
- JavaScript - switch case
- JavaScript - 使用者定義迭代器
- JavaScript 函式
- JavaScript - 函式
- JavaScript - 函式表示式
- JavaScript - 函式引數
- JavaScript - 預設引數
- JavaScript - Function() 建構函式
- JavaScript - 函式提升
- JavaScript - 自執行函式
- JavaScript - 箭頭函式
- JavaScript - 函式呼叫
- JavaScript - Function call()
- JavaScript - Function apply()
- JavaScript - Function bind()
- JavaScript - 閉包
- JavaScript - 變數作用域
- JavaScript - 全域性變數
- JavaScript - 智慧函式引數
- JavaScript 物件
- JavaScript - Number
- JavaScript - Boolean
- JavaScript - String
- JavaScript - Array
- JavaScript - Date
- JavaScript - DataView
- JavaScript - Handler
- JavaScript - Math
- JavaScript - RegExp
- JavaScript - Symbol
- JavaScript - Set
- JavaScript - WeakSet
- JavaScript - Map
- JavaScript - WeakMap
- JavaScript - 可迭代物件
- JavaScript - Reflect
- JavaScript - TypedArray
- JavaScript - 模板字面量
- JavaScript - 標籤模板
- 面向物件 JavaScript
- JavaScript - 物件
- JavaScript - 類
- JavaScript - 物件屬性
- JavaScript - 物件方法
- JavaScript - 靜態方法
- JavaScript - 顯示物件
- JavaScript - 物件訪問器
- JavaScript - 物件建構函式
- JavaScript - 原生原型
- JavaScript - ES5 物件方法
- JavaScript - 封裝
- JavaScript - 繼承
- JavaScript - 抽象
- JavaScript - 多型
- JavaScript - 解構賦值
- JavaScript - 物件解構
- JavaScript - 陣列解構
- JavaScript - 巢狀解構
- JavaScript - 可選鏈
- JavaScript - 全域性物件
- JavaScript - Mixins
- JavaScript - 代理 (Proxies)
- JavaScript 版本
- JavaScript - 歷史
- JavaScript - 版本
- JavaScript - ES5
- JavaScript - ES6
- ECMAScript 2016
- ECMAScript 2017
- ECMAScript 2018
- ECMAScript 2019
- ECMAScript 2020
- ECMAScript 2021
- ECMAScript 2022
- JavaScript 非同步
- JavaScript - 非同步
- JavaScript - 回撥函式
- JavaScript - Promise
- JavaScript - Async/Await
- JavaScript - 微任務
- JavaScript - Promise 化
- JavaScript - Promise 鏈式呼叫
- JavaScript - 定時事件
- JavaScript - setTimeout()
- JavaScript - setInterval()
- JavaScript Cookie
- JavaScript - Cookie
- JavaScript - Cookie 屬性
- JavaScript - 刪除 Cookie
- JavaScript 瀏覽器 BOM
- JavaScript - 瀏覽器物件模型
- JavaScript - Window 物件
- JavaScript - Document 物件
- JavaScript - Screen 物件
- JavaScript - History 物件
- JavaScript - Navigator 物件
- JavaScript - Location 物件
- JavaScript - Console 物件
- JavaScript Web APIs
- JavaScript - Web API
- JavaScript - History API
- JavaScript - Storage API
- JavaScript - Forms API
- JavaScript - Worker API
- JavaScript - Fetch API
- JavaScript - Geolocation API
- JavaScript 事件
- JavaScript - 事件
- JavaScript - DOM 事件
- JavaScript - addEventListener()
- JavaScript - 滑鼠事件
- JavaScript - 鍵盤事件
- JavaScript - 表單事件
- JavaScript - Window/Document 事件
- JavaScript - 事件委託
- JavaScript - 事件冒泡
- JavaScript - 事件捕獲
- JavaScript - 自定義事件
- JavaScript 錯誤處理
- JavaScript - 錯誤處理
- JavaScript - try...catch
- JavaScript - 除錯
- JavaScript - 自定義錯誤
- JavaScript - 擴充套件錯誤
- JavaScript 重要關鍵字
- JavaScript - this 關鍵字
- JavaScript - void 關鍵字
- JavaScript - new 關鍵字
- JavaScript - var 關鍵字
- JavaScript HTML DOM
- JavaScript - HTML DOM
- JavaScript - DOM 方法和屬性
- JavaScript - DOM Document
- JavaScript - DOM 元素
- JavaScript - DOM 屬性 (Attr)
- JavaScript - DOM 表單
- JavaScript - 修改 HTML
- JavaScript - 修改 CSS
- JavaScript - DOM 動畫
- JavaScript - DOM 導航
- JavaScript - DOM 集合
- JavaScript - DOM NodeList
- JavaScript - DOM DOMTokenList
- JavaScript 其他
- JavaScript - Ajax
- JavaScript - 非同步迭代
- JavaScript - Atomics 物件
- JavaScript - rest 引數
- JavaScript - 頁面重定向
- JavaScript - 對話方塊
- JavaScript - 頁面列印
- JavaScript - 驗證
- JavaScript - 動畫
- JavaScript - 多媒體
- JavaScript - 圖片地圖
- JavaScript - 瀏覽器
- JavaScript - JSON
- JavaScript - 多行字串
- JavaScript - 日期格式
- JavaScript - 獲取日期方法
- JavaScript - 設定日期方法
- JavaScript - 模組
- JavaScript - 動態匯入
- JavaScript - BigInt
- JavaScript - Blob
- JavaScript - Unicode
- JavaScript - 淺複製
- JavaScript - 呼叫棧
- JavaScript - 引用型別
- JavaScript - IndexedDB
- JavaScript - 點選劫持攻擊
- JavaScript - 柯里化
- JavaScript - 圖形
- JavaScript - Canvas
- JavaScript - 防抖
- JavaScript - 效能
- JavaScript - 樣式指南
JavaScript - 非同步迭代
非同步迭代
在 JavaScript 中,非同步迭代指的是迭代非同步序列或集合的能力,例如非同步函式或生成器返回的那些序列或集合。非同步迭代通常與涉及非同步任務的操作一起使用,例如從遠端伺服器獲取資料或從檔案讀取資料。
理解非同步操作
簡單來說,程式設計中的非同步操作是指在等待完成期間不會阻塞程式執行的任務或過程。這些非同步任務使程式能夠在等待當前任務完成的同時繼續執行其他任務,而不是在繼續下一個任務之前暫停等待每個操作完成。
使用 'for await...of' 迴圈
for await...of 迴圈用於非同步迭代。它的工作方式與常規的 for...of 迴圈類似,但它設計用於與非同步迭代器一起工作。非同步迭代器是一個定義了 async next() 方法的物件,該方法返回對序列中下一個值的承諾。
示例:使用 Promise
JavaScript 使用 Promise 來處理非同步操作;Promise 代表非同步操作的結果(成功或失敗)。這裡,函式 asyncOperation 模擬這樣的操作,返回一個 Promise。for await...of 迴圈優雅地遍歷非同步序列,突出了在管理非阻塞操作時使用 Promise 的方式,而不會影響程式碼的可讀性。
<!DOCTYPE html> <html> <body> <h2>Async Iteration with Promises</h2> <div id="output"></div> <script> function asyncOperation(value) { return new Promise(resolve => { setTimeout(() => { document.getElementById('output').innerHTML += `<p>Processed: ${value}</p>`; resolve(value); }, 1000); }); } const asyncIterable = { [Symbol.asyncIterator]: async function* () { for (let i = 1; i <= 3; i++) { yield await asyncOperation(i); } }, }; async function processAsyncIterable() { for await (const result of asyncIterable) { document.getElementById('output').innerHTML += `<p>Received: ${result}</p>`; } } processAsyncIterable(); </script> </body> </html>
示例 2:使用 Fetch API 進行非同步 HTTP 請求
在這裡,我們演示了使用 Fetch API 進行 HTTP 請求的非同步迭代:asyncIterable 以非同步方式獲取資料。此外,使用 for await...of 迴圈優雅地遍歷結果,展示了非同步迭代與從外部資料來源檢索資料如何無縫結合。
<!DOCTYPE html> <html> <body> <h2>Async Iteration with Fetch API</h2> <div id="output"></div> <script> const url = 'https://jsonplaceholder.typicode.com/todos/'; const asyncIterable = { [Symbol.asyncIterator]: async function* () { for (let i = 1; i <= 3; i++) { const response = await fetch(`${url}${i}`); const data = await response.json(); document.getElementById('output').innerHTML += `<p>Received: ${JSON.stringify(data)}</p>`; yield data; } }, }; async function processAsyncIterable() { for await (const result of asyncIterable) { // Already displaying results above, no need for additional output. } } processAsyncIterable(); </script> </body> </html>
示例 3:使用回撥函式
這種方法使用基於回撥的方法來實現非同步迭代。函式 asyncOperation 模擬非同步任務並在完成時進行回撥。同時,processAsyncIterable 函式積極地遍歷陣列,為每個元素呼叫非同步操作。
<!DOCTYPE html> <html> <body> <h2>Async Iteration with callback</h2> <div id="output"></div> <script> function asyncOperation(value, callback) { setTimeout(() => { document.getElementById('output').innerHTML += `<p>Processed: ${value}</p>`; callback(value); }, 1000); } function processAsyncIterable(iterable, callback) { const iterator = iterable[Symbol.iterator](); function iterate() { const next = iterator.next(); if (next.done) { return; } const value = next.value; asyncOperation(value, result => { document.getElementById('output').innerHTML += `<p>Received: ${result}</p>`; iterate(); }); } iterate(); } const asyncIterable = [5,6,7,8,9,10]; processAsyncIterable(asyncIterable, result => { // You can handle final result or additional actions here if needed. }); </script> </body> </html>
示例 4:帶有錯誤的 Promise
JavaScript 中的 .then() 方法使用一個或兩個回撥函式來處理 Promise 的成功解析:如果 promise 解析成功,則執行第一個函式;如果 promise 拒絕,則執行可選的第二個函式。
.catch() 方法用於處理 Promise 的拒絕。當 promise 拒絕時,將執行一個回撥函式;這為處理非同步操作中的錯誤提供了一種優雅的解決方案,無需專門用於錯誤處理的 .then() 塊。
<!DOCTYPE html> <html> <head> <style> #output { margin-top: 20px; } </style> </head> <body> <h2>Async Iteration with Promises</h2> <button onclick="startAsyncIteration()">Start Async Iteration</button> <div id="output"></div> <script> function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function fetchData(index) { return new Promise((resolve, reject) => { if (index < 5) { delay(1000).then(() => resolve(`Data ${index}`)); } else { // Simulate an error for index 5 reject(new Error('Error fetching data for index 5')); } }); } function startAsyncIteration() { document.getElementById('output').innerHTML = ''; let index = 0; function iterate() { fetchData(index) .then(data => { displayData(data); index++; if (index < 6) { iterate(); } }) .catch(error => { // Display error on the page. displayError(error.message); }); } iterate(); } function displayData(data) { const outputDiv = document.getElementById('output'); outputDiv.innerHTML += `<p>Data received: ${data}</p>`; } function displayError(errorMessage) { const outputDiv = document.getElementById('output'); outputDiv.innerHTML += `<p style="color: red;">Error: ${errorMessage}</p>`; } </script> </body> </html>
現實世界中的用例
在現實世界中,我們使用 JavaScript 非同步迭代來最佳化各種非同步操作:在 Web 應用程式中同時從多個 API 獲取資料;處理即時更新(對於聊天系統至關重要);執行需要大量資源的批次任務或並行任務;處理檔案操作和流;處理互動式 Web 頁面上的併發使用者互動;處理來自物聯網裝置的資料;動態載入網頁內容;以及離線優先應用程式的資料同步等。