JavaScript: Funções Generator Assíncronas
19052 단어 webdevjavascriptptbrnode
for/await/of
para o JavaScript também introduziu o conceito de uma função generator assíncrona . Agora, o JavaScript 항목 6 팁 기능 구분:function() {}
() => {}
async function() {}
async () => {}
function*() {}
async function*() {}
As funções generator assíncronas são especiais porque você pode usar ambos
await
e yield
em uma função generator assíncrona. As funções generator assíncrona diferem das funções assíncrona e funções generator porque não retornam uma promessa ou um iterador, mas sim um iterador assíncrono . Você pode pensar em um iterador assíncrono como um iterador onde a função next()
semper retorna uma promessa.Sua Primeira Função Generator assincrona
As funções generator assíncronas se comportam de maneira semelhante à as funções generator: a função generator retorna um objeto que tem uma função
next()
e a chamada next()
executa atyield
executa 발전기 A diferença é que a função next()
de um iterador assíncrono retorna uma promessa .Abaixo está um exemplo "Hello, World"com funções generator assíncrona. Node.js anteriores a 10.x의 기능 스크립트를 관찰하십시오.
'usze strict';
async function* run() {
// Dorme por 100ms, see: https://masteringjs.io/tutorials/fundamentals/sleep
await new Promise(resolve => setTimeout(resolve, 100));
yield 'Hello';
console.log('World');
}
// `run()` retorna um iterador assíncrono.
const asyncIterator = run();
// A função não é executada até `next()` ser chamado
asyncIterator.next().
then(obj => console.log(obj.value)). // Prints "Hello"
then(() => asyncIterator.next()); // Prints "World"
A maneira mais limpa de fazer um loop em todos valores de uma função generator assíncrona é usando um
for/await/of
.'use strict';
async function* run() {
await new Promise(resolve => setTimeout(resolve, 100));
yield 'Hello';
console.log('World');
}
const asyncIterator = run();
// Imprimi "Hello\nWorld"
(async () => {
for await (const val of asyncIterator) {
console.log(val); // Imprimi "Hello"
}
})();
Um caso de uso prático
Você pode estar pensando "JavaScript precisa de funções 생성기 assíncronas quando já tem funções assíncronas e funções 생성기?"Um caso de uso é o problema classico da barra de progresso em que Ryan Dahl originalmente escreveu Node.js para resolver .
Suponha que você deseja percorrer todos os documentos em um cursor Mongoose e relatar o progresso via websocket ou para a linha de comando.
'use strict';
const mongoose = require('mongoose');
async function* run() {
await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
await mongoose.connection.dropDatabase();
const Model = mongoose.model('Test', mongoose.Schema({ name: String }));
for (let i = 0; i < 5; ++i) {
await Model.create({ name: `doc ${i}` });
}
// Supondo que você tenha vários documentos e você quer reportar o progresso
// de cada um. Você pode usar `yield` após processar cada documento.
const total = 5;
const cursor = Model.find().cursor();
let processed = 0;
for await (const doc of cursor) {
// Você pode pensar em `yield` como reportando: "Finalizei uma unidade de trabalho"
yield { processed: ++processed, total };
}
}
(async () => {
for await (const val of run()) {
// Imprimi "1 / 5", "2 / 5", "3 / 5", etc.
console.log(`${val.processed} / ${val.total}`);
}
})();
As funções generator assíncronas tornam mais fácil para sua função assíncrona relatar seu progresso de uma forma sem frameworks . Não há necessidade de criar 명시적 웹소켓 ou log no console - você pode lidar com isso separadamente se assumir que sua lógica de negócios usa
yield
para relatar seu progresso.Com Observáveis
Os iteradores assíncronos são ótimos, mas há outra primitiva de simultaneidade com a qual as funções generator assíncronas se alinham bem: os observáveis RxJS .
'use strict';
const { Observable } = require('rxjs');
const mongoose = require('mongoose');
async function* run() {
// Mesmo código de antes
}
// Cria um observável que emite cada valor que o iterador assíncrono retorna
const observable = Observable.create(async (observer) => {
for await (const val of run()) {
observer.next(val);
}
});
// Imprimi "1 / 5", "2 / 5", "3 / 5", etc.
observable.subscribe(val => console.log(`${val.processed} / ${val.total}`));
Existem duas diferenças principais entre usar um observável RxJS e um iterador assíncrono. Primeiro, no exemplo acima, o codigo que se conecta ao console
subscribe()
é reativo, e não imperativo . Em outras palavras, o manipulador subscribe()
não tem como afetar o codigo no corpo da função assíncrona, ele simplesmente reage aos eventos. Ao usar um for/await/of
loop, você pode, por exemplo, adicionar uma pausa de 1 segundo antes de retomar a função generator assíncrona.(async () => {
for await (const val of run()) {
// Imprimi "1 / 5", "2 / 5", "3 / 5", etc.
console.log(`${val.processed} / ${val.total}`);
// Adiciona 1 segundo de delay para cada instrução `yield`
await new Promise(resolve => setTimeout(resolve, 1000));
}
})();
A segunda é que, como os observáveis RxJS são frios por padrão , uma nova chamada
subscribe()
executa novamente a função.피날리잔도
기능 생성기 assíncronas podem parecer de nicho e confusas no início, mas fornecem o que pode se tornar a solução nativa do JavaScript para problemas de "barra de progresso". Usar yield
para relatar o progresso de uma função assíncrona é uma ideia atraente porque permite que você desacople sua lógica de negócios de sua estrutura de relatório de progresso. Dê uma 기회 aos generators assíncronos na próxima vez que precisar implementationar uma barra de progresso.
신용
Async Generator Functions in JavaScript, escrito originalmente por .
Reference
이 문제에 관하여(JavaScript: Funções Generator Assíncronas), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/oieduardorabelo/javascript-funcoes-generator-assincronas-5eb0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)