이 글에서는 Node.js의 비동기 반복자를 소개합니다. 도움이 필요한 친구들이 모두 참고할 수 있기를 바랍니다.
비동기 반복자는 버전 10.0.0부터 Node에서 사용할 수 있습니다. 이 기사에서는 비동기 반복자의 역할과 사용할 수 있는 위치에 대해 설명합니다.
비동기 반복기는 실제로 이전 반복기의 비동기 버전입니다. 비동기 반복자는 반복의 값과 최종 상태를 알 수 없을 때 사용할 수 있습니다. 둘 사이의 차이점은 우리가 얻는 promise가 결국 일반 { value: any, done: boolean }
객체로 분해된다는 것입니다. 또한 for-await-로 전달할 수도 있습니다. of
비동기 반복자를 처리하는 루프입니다. for-of
루프가 반복자를 동기화하는 데 사용되는 것과 같습니다. [관련 권장사항: "nodejs tutorial{ value: any, done: boolean }
对象,另外可以通过 for-await-of
循环来处理异步迭代器。就像 for-of
循环用于同步迭代器一样。【相关推荐:《nodejs 教程》】
const asyncIterable = [1, 2, 3]; asyncIterable[Symbol.asyncIterator] = async function*() { for (let i = 0; i < asyncIterable.length; i++) { yield { value: asyncIterable[i], done: false } } yield { done: true }; }; (async function() { for await (const part of asyncIterable) { console.log(part); } })();
与通常的 for-of
循环相反,`for-await-of
循环将会等待它收到的每个 promise 解析之后再继续执行下一个。
除了流之外,还在还没有什么能够支持异步迭代的结构,但是可以将 asyncIterator
符号手动添加到任何一种可迭代的结构中。
异步迭代器在处理流时非常有用。可读流、可写流、双工流和转换流上都带有 asyncIterator
符号。
async function printFileToConsole(path) { try { const readStream = fs.createReadStream(path, { encoding: 'utf-8' }); for await (const chunk of readStream) { console.log(chunk); } console.log('EOF'); } catch(error) { console.log(error); } }
如果以这种方式写代码,就不需要在通过迭代获取每个数据块时监听 end
和 data
事件了,并且 for-await-of
循环会随着流的结束而结束。
你还可以通过异步迭代从使用分页的源中轻松获取数据。为了实现这个功能,还需要一种从Node https 请求方法提供给的流中重构响应主体的方法。在这里也可以使用异步迭代器,因为 https 请求和响应在 Node 中都是流:
const https = require('https'); function homebrewFetch(url) { return new Promise(async (resolve, reject) => { const req = https.get(url, async function(res) { if (res.statusCode >= 400) { return reject(new Error(`HTTP Status: ${res.statusCode}`)); } try { let body = ''; /* 代替 res.on 侦听流中的数据, 可以使用 for-await-of, 并把数据块附加到到响应体的剩余部分 */ for await (const chunk of res) { body += chunk; } // 处理响应没有响应体的情况 if (!body) resolve({}); // 需要解析正文来获取 json,因为它是一个字符串 const result = JSON.parse(body); resolve(result); } catch(error) { reject(error) } }); await req; req.end(); }); }
代码通过向 Cat API(https://thecatapi.com/)发出请求,来获取一些猫的图片。另外还添加了 7 秒钟的延迟防止对 cat API 的访问过与频繁,因为那样是极其不道德的。
function fetchCatPics({ limit, page, done }) { return homebrewFetch(`https://api.thecatapi.com/v1/images/search?limit=${limit}&page=${page}&order=DESC`) .then(body => ({ value: body, done })); } function catPics({ limit }) { return { [Symbol.asyncIterator]: async function*() { let currentPage = 0; // 5 页后停止 while(currentPage < 5) { try { const cats = await fetchCatPics({ currentPage, limit, done: false }); console.log(`Fetched ${limit} cats`); yield cats; currentPage ++; } catch(error) { console.log('There has been an error fetching all the cats!'); console.log(error); } } } }; } (async function() { try { for await (let catPicPage of catPics({ limit: 10 })) { console.log(catPicPage); // 每次请求之间等待 7 秒 await new Promise(resolve => setTimeout(resolve, 7000)); } } catch(error) { console.log(error); } })()
这样,我们就会每隔7秒钟自动取回一整页的喵星人图片。
一种更常见的页面间导航的方法可实现 next
和 previous
"]
function actualCatPics({ limit }) { return { [Symbol.asyncIterator]: () => { let page = 0; return { next: function() { page++; return fetchCatPics({ page, limit, done: false }); }, previous: function() { if (page > 0) { page--; return fetchCatPics({ page, limit, done: false }); } return fetchCatPics({ page: 0, limit, done: true }); } } } }; } try { const someCatPics = actualCatPics({ limit: 5 }); const { next, previous } = someCatPics[Symbol.asyncIterator](); next().then(console.log); next().then(console.log); previous().then(console.log); } catch(error) { console.log(error); }
그리고 일반적으로 for-of
루프와 달리 `for-await-of
루프는 다음 약속을 계속하기 전에 수신한 각 약속이 해결될 때까지 기다립니다.
스트림을 제외하고 비동기 반복을 지원하는 구조는 없지만 asyncIterator
기호는 반복 가능한 구조에 수동으로 추가할 수 있습니다.
스트림에서 비동기 반복자 사용
비동기 반복자는 스트림 작업 시 매우 유용합니다. 읽기 가능한 스트림, 쓰기 가능한 스트림, 이중 스트림 및 변환 스트림은 모두 asyncIterator
기호로 표시됩니다. rrreee 이런 식으로 코드를 작성하면 각 데이터 청크를 반복할 때 end
및 data
이벤트를 수신할 필요가 없으며 for- 스트림이 끝나면 대기
루프가 종료됩니다.
next
및 previous
메서드를 구현하고 이를 컨트롤로 노출하는 것입니다. 🎜rrreee🎜보시다시피 원할 때 get 비동기 반복자는 데이터 페이지나 프로그램 UI에서 무한 스크롤과 같은 작업을 수행할 때 매우 유용할 수 있습니다. 🎜🎜이 기능은 Chrome 63+, Firefox 57+, Safari 11.1+에서 사용할 수 있습니다. 🎜🎜아직도 비동기 반복자를 어디에 사용할 수 있는지 생각해 볼 수 있나요? 아래에 메시지를 남겨주세요! 🎜🎜더 많은 프로그래밍 관련 지식을 보려면 🎜프로그래밍 비디오🎜를 방문하세요! ! 🎜위 내용은 Node.js 비동기 반복자 및 사용 방법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!