developer tip

생성기를 사용한 비동기 / 대기 및 ES6 수율의 차이점

optionbox 2020. 11. 15. 11:12
반응형

생성기를 사용한 비동기 / 대기 및 ES6 수율의 차이점


저는이 환상적인 기사를 읽고있었습니다.

https://www.promisejs.org/generators/

제너레이터 함수를 처리하기위한 도우미 함수 인이 함수를 명확하게 강조합니다.

function async(makeGenerator){
  return function () {
    var generator = makeGenerator.apply(this, arguments);

    function handle(result){
      // result => { done: [Boolean], value: [Object] }
      if (result.done) return Promise.resolve(result.value);

      return Promise.resolve(result.value).then(function (res){
        return handle(generator.next(res));
      }, function (err){
        return handle(generator.throw(err));
      });
    }

    try {
      return handle(generator.next());
    } catch (ex) {
      return Promise.reject(ex);
    }
  }
}

나는 async 키워드가 구현되는 방식과 다소 비슷하다고 가정합니다 async/await. 그렇다면 문제는 await키워드와 키워드 의 차이점이 도대체 무엇 yield일까요? 않는 await반면 항상 약속에 뭔가를 돌려 yield그러한 보증을하지 않습니다? 그것은 내 최선의 추측입니다!

또한 'spawn'함수를 설명하는이 기사에서 async / await가 생성기를 사용한 yield와 어떻게 유사한 지 확인할 수 있습니다. https://jakearchibald.com/2014/es7-async-functions/


yield의 빌딩 블록으로 간주 될 수 있습니다 await. yield주어진 값을 받아 호출자에게 전달합니다. 그런 다음 호출자는 해당 값 (1)으로 원하는 모든 작업을 수행 할 수 있습니다. 나중에 호출자는 (2) 표현식 generator.next()의 결과가되는 생성자 (를 통해 )에 값을 다시 제공 yield하거나 yield(3) 표현식에 의해 throw되는 것처럼 보이는 오류를 제공 할 수 있습니다 .

async- await를 사용하는 것으로 간주 할 수 있습니다 yield. (즉, (1) 호출자에 async- await드라이버 - 당신이 게시 된 기능과 유사)와 유사한 알고리즘을 사용하여 약속의 값을 바꿈됩니다 new Promise(r => r(value)(참고, 하지 Promise.resolve ,하지만 그건 큰 문제가 아니다). 그런 다음 약속이 해결 될 때까지 기다립니다. 충족되면 충족 된 값을 (2)로 다시 전달합니다. 거부하면 (3)에서 오류로 거부 사유를 던집니다.

따라서 async- 의 유용성은 산출 된 값을 약속으로 풀고 해결 된 값을 다시 전달하여 함수가 최종 값을 반환 할 때까지 반복 await하는 데 사용 yield하는 이 기계입니다 .


음, async / await와 생성기 사이에는 매우 밀접한 관계가 있다는 것이 밝혀졌습니다. 그리고 async / await는 항상 제너레이터에 구축 될 것이라고 믿습니다. Babel이 async / await를 변환하는 방식을 살펴보면 :

Babel은 다음을 수행합니다.

this.it('is a test', async function () {

    const foo = await 3;
    const bar = await new Promise(resolve => resolve('7'));
    const baz = bar * foo;
    console.log(baz);

});

그리고 이것을 이렇게

function _asyncToGenerator(fn) {
    return function () {
        var gen = fn.apply(this, arguments);
        return new Promise(function (resolve, reject) {
            function step(key, arg) {
                try {
                    var info = gen[key](arg);
                    var value = info.value;
                } catch (error) {
                    reject(error);
                    return;
                }
                if (info.done) {
                    resolve(value);
                } else {
                    return Promise.resolve(value).then(function (value) {
                        return step("next", value);
                    }, function (err) {
                        return step("throw", err);
                    });
                }
            }

            return step("next");
        });
    };
}


this.it('is a test', _asyncToGenerator(function* () {   // << now it's a generator

    const foo = yield 3;    //  <<< now it's yield, not await
    const bar = yield new Promise(resolve => resolve(7));
    const baz = bar * foo;
    console.log(baz);

}));

당신은 수학을합니다.

이것은 async 키워드가 단지 그 래퍼 함수 인 것처럼 보이게하지만, 만약 그렇다면 await가 yield로 바뀌면 나중에 네이티브가 될 때 그림에 약간 더 많은 것이있을 것입니다.

이에 대한 자세한 설명은 https://www.promisejs.org/generators/ 에서 확인할 수 있습니다.


도대체 await키워드와 키워드 의 차이점은 무엇 yield입니까?

The await keyword is only to be used in async functions, while the yield keyword is only to be used in generator function*s. And those are obviously different as well - the one returns promises, the other returns generators.

Does await always turn something into a promise, whereas yield makes no such guarantee?

Yes, await will call Promise.resolve on the awaited value.

yield just yields the value outside of the generator.


tldr;

Use Async/Await 99% of the time over Generators. Why?

  1. Async/Await directly replaces the most common work-flow of promise chains allowing code to be declared as if it was synchronous, dramatically simplifying it.

  2. 생성기는 서로 의존하고 결국 "완료"상태가되는 일련의 비동기 작업을 호출하는 사용 사례를 추상화합니다. 가장 간단한 예는 결국 마지막 세트를 반환하는 결과를 통해 페이징하는 것이지만 연속적으로 즉시 호출하지 않고 필요한 경우에만 페이지를 호출합니다.

  3. Async / Await는 실제로 Promise 작업을 더 쉽게하기 위해 Generators 위에 구축 된 추상화입니다.

Async / Await vs. Generators에 대한 자세한 설명보기


약속과 함께 대기 / 비동기를 이해하는 데 사용한이 테스트 프로그램을 사용해보십시오.

프로그램 # 1 : 약속없이 순서대로 실행되지 않음

function functionA() {
    console.log('functionA called');
    setTimeout(function() {
        console.log('functionA timeout called');
        return 10;
    }, 15000);

}

function functionB(valueA) {
    console.log('functionB called');
    setTimeout(function() {
        console.log('functionB timeout called = ' + valueA);
        return 20 + valueA;
    }, 10000);
}

function functionC(valueA, valueB) {

    console.log('functionC called');
    setTimeout(function() {
        console.log('functionC timeout called = ' + valueA);
        return valueA + valueB;
    }, 10000);

}

async function executeAsyncTask() {
    const valueA = await functionA();
    const valueB = await functionB(valueA);
    return functionC(valueA, valueB);
}
console.log('program started');
executeAsyncTask().then(function(response) {
    console.log('response called = ' + response);
});
console.log('program ended');

프로그램 2 : 약속 있음 :

function functionA() {
    return new Promise((resolve, reject) => {
        console.log('functionA called');
        setTimeout(function() {
            console.log('functionA timeout called');
            // return 10;
            return resolve(10);
        }, 15000);
    });   
}

function functionB(valueA) {
    return new Promise((resolve, reject) => {
        console.log('functionB called');
        setTimeout(function() {
            console.log('functionB timeout called = ' + valueA);
            return resolve(20 + valueA);
        }, 10000);

    });
}

function functionC(valueA, valueB) {
    return new Promise((resolve, reject) => {
        console.log('functionC called');
        setTimeout(function() {
            console.log('functionC timeout called = ' + valueA);
            return resolve(valueA + valueB);
        }, 10000);

    });
}

async function executeAsyncTask() {
    const valueA = await functionA();
    const valueB = await functionB(valueA);
    return functionC(valueA, valueB);
}
console.log('program started');
executeAsyncTask().then(function(response) {
    console.log('response called = ' + response);
});
console.log('program ended');

In many ways, generators are a superset of async/await. Right now async/await has cleaner stack traces than co, the most popular async/await-like generator based lib. You can implement your own flavor of async/await using generators and add new features, like built-in support for yield on non-promises or building it on RxJS observables.

So, in short, generators give you more flexibility and generator-based libs generally have more features. But async/await is a core part of the language, it's standardized and won't change under you, and you don't need a library to use it. I have a blog post with more details on the difference between async/await and generators.

참고URL : https://stackoverflow.com/questions/36196608/difference-between-async-await-and-es6-yield-with-generators

반응형