정보실

웹학교

정보실

javascript JavaScript의 비동기 생성기 함수

본문

JavaScript를 위한 / await / 제시 한 TC39 async iterators 제안은 async generator function의 개념을 도입했습니다. 이제 JavaScript에는 6 가지 유형의 함수가 있습니다.

  • 일반 함수 function() {}
  • 화살표 함수 () => {}
  • 비동기 함수 async function() {}
  • 비동기 화살표 함수 async () => {}
  • 생성기 함수 function * () {}
  • 비동기 생성기 함수 async function*() {}


http://thecodebarbarian.com/async-generator-functions-in-javascript.html 


비동기 생성기 함수는 비동기 생성기 함수에서 await 및 yield를 모두 사용할 수 있기 때문에 특별합니다. 비동기 생성기 함수는 promise 또는 반복자를 반환하지 않고 비동기 반복기를 반환한다는 점에서 비동기 함수 및 생성기 함수와 다릅니다. 비동기 반복자를 next() 함수가 항상 약속을 반환하는 반복자로 생각할 수 있습니다.


첫 비동기 생성기 함수 


비동기 생성기 함수는 생성기 함수와 유사하게 작동합니다. 생성기 함수는 next() 함수가 있는 객체를 반환하고 next()를 호출하면 다음 수율까지 생성기 함수가 실행됩니다. 차이점은 비동기 반복기의 next() 함수가 약속을 반환한다는 것입니다.


아래는 비동기 생성기 함수가 있는 "Hello, World"예제입니다. 아래 스크립트는 10.x 이전의 Node.js 버전에서는 작동하지 않습니다.


'use strict';

async function* run() {
  await new Promise(resolve => setTimeout(resolve, 100));
  yield 'Hello';
  console.log('World');
}

// `run()` returns an async iterator.
const asyncIterator = run();

// The function doesn't start running until you call `next()`
asyncIterator.next().
  then(obj => console.log(obj.value)). // Prints "Hello"
  then(() => asyncIterator.next());  // Prints "World"

전체 비동기 생성기 함수를 반복하는 가장 깨끗한 방법은 for / await / of 루프를 사용하는 것입니다.


'use strict';

async function* run() {
  await new Promise(resolve => setTimeout(resolve, 100));
  yield 'Hello';
  console.log('World');
}

const asyncIterator = run();

// Prints "Hello\nWorld"
(async () => {
  for await (const val of asyncIterator) {
    console.log(val); // Prints "Hello"
  }
})();


실용 사례 


"동기화 함수와 생성기 함수가 이미 있는 JavaScript가 왜 비동기 생성기 함수가 필요한가?" 한 가지 사용 사례는 Ryan Dahl이 원래 Node.js를 작성하여 해결 한 전형적인 진행률 표시 줄 문제입니다.


몽구스 커서의 모든 문서를 반복하고 웹 소켓 또는 명령 행을 통해 진행 상황을 보고 한다고 가정합니다.


'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}` });
  }

  // Suppose you have a lot of documents and you want to report when you process
  // each one. You can `yield` after processing each individual doc.
  const total = 5;
  const cursor = Model.find().cursor();

  let processed = 0;
  for await (const doc of cursor) {
    // You can think of `yield` as reporting "I'm done with one unit of work"
    yield { processed: ++processed, total };
  }
}

(async () => {
  for await (const val of run()) {
    // Prints "1 / 5", "2 / 5", "3 / 5", etc.
    console.log(`${val.processed} / ${val.total}`);
  }
})();

비동기 생성기 함수를 사용하면 비동기 함수가 프레임 워크 없이 진행 상황을 쉽게 보고 할 수 있습니다. 웹 소켓을 명시 적으로 작성하거나 콘솔에 로그인 할 필요가 없습니다. 비즈니스 로직이 진행률 보고에 수확량을 사용한다고 가정하면 별도로 처리 할 수 ​​있습니다.


관찰 가능 


비동기 반복기는 훌륭하지만 비동기 생성기 함수가 RxJS 옵저버 블과 잘 일치하는 또 다른 동시성 기본 요소가 있습니다.


'use strict';

const { Observable } = require('rxjs');
const mongoose = require('mongoose');

async function* run() {
  // Same as before
}

// Create an observable that emits each value the async generator yields
// to subscribers.
const observable = Observable.create(async (observer) => {
  for await (const val of run()) {
    observer.next(val);
  }
});

// Prints "1 / 5", "2 / 5", "3 / 5", etc.
observable.subscribe(val => console.log(`${val.processed} / ${val.total}`));

RxJS 옵저버 블과 비동기 반복자를 사용하는 것에는 두 가지 주요 차이점이 있습니다. 먼저, 위의 예제에서 subscribe()로 콘솔에 기록하는 코드는 명령적인 것이 아니라 반응 적입니다. 즉, subscribe() 핸들러는 비동기 함수 본문의 코드에 영향을 줄 수 있는 방법이 없으며 단순히 이벤트에 반응합니다. 예를 들어 for / await / of 루프를 사용하는 경우 비동기 생성기 함수를 다시 시작하기 전에 1 초 동안 일시 중지 할 수 있습니다.


(async () => {
  for await (const val of run()) {
    // Prints "1 / 5", "2 / 5", "3 / 5", etc.
    console.log(`${val.processed} / ${val.total}`);
    // This adds a 1 second delay to every `yield` statement.
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
})();

두 번째는 RxJS 옵저버 블이 기본적으로 콜드 이므로 새로운 subscribe() 호출이 함수를 다시 실행한다는 것입니다.


// Prints "1 / 5", "2 / 5", "3 / 5", etc.
observable.subscribe(val => console.log(`${val.processed} / ${val.total}`));
// Kicks off a separate instance of `run()`
observable.subscribe(val => console.log(`${val.processed} / ${val.total}`));

계속 


비동기 생성기 함수는 처음에는 틈새 및 혼란스러워 보일 수 있지만 진행률 표시 줄 문제에 대한 JavaScript의 기본 솔루션이 될 수 있습니다. 수율을 사용하여 비동기 함수의 진행률을 보고하는 것은 비즈니스 로직을 진행률 보고 프레임 워크에서 분리 할 수 ​​있기 때문에 매력적인 아이디어입니다. 다음에 진행률 표시 줄을 구현해야 할 때 비동기 생성기에 샷을 제공하십시오.










  • 트위터로 보내기
  • 페이스북으로 보내기
  • 구글플러스로 보내기
  • 카카오톡으로 보내기

페이지 정보

조회 3회 ]  작성일19-08-15 10:23

웹학교