Implementing coroutine control flow in JavaScript

后端 未结 2 762
深忆病人
深忆病人 2020-12-04 04:00

The following implements a control flow wrapper co enabling asynchronous code to be delineated only by the yield keyword.

Is this basically

相关标签:
2条回答
  • 2020-12-04 04:33

    Stage 3 Draft / January 26, 2016 Async Functions provides examples of three patterns; Promise; Generator; Async Functions; where the distinct approaches essentially produce the same result

    Examples#

    Take the following example, first written using Promises. This code chains a set of animations on an element, stopping when there is an exception in an animation, and returning the value produced by the final succesfully executed animation.

    function chainAnimationsPromise(elem, animations) {
        let ret = null;
        let p = currentPromise;
        for(const anim of animations) {
            p = p.then(function(val) {
                ret = val;
                return anim(elem);
            })
        }
        return p.catch(function(e) {
            /* ignore and keep going */
        }).then(function() {
            return ret;
        });
    }
    

    Already with promises, the code is much improved from a straight callback style, where this sort of looping and exception handling is challenging.

    Task.js and similar libraries offer a way to use generators to further simplify the code maintaining the same meaning:

    function chainAnimationsGenerator(elem, animations) {
        return spawn(function*() {
            let ret = null;
            try {
                for(const anim of animations) {
                    ret = yield anim(elem);
                }
            } catch(e) { /* ignore and keep going */ }
            return ret;
        });
    }
    

    This is a marked improvement. All of the promise boilerplate above and beyond the semantic content of the code is removed, and the body of the inner function represents user intent. However, there is an outer layer of boilerplate to wrap the code in an additional generator function and pass it to a library to convert to a promise. This layer needs to be repeated in every function that uses this mechanism to produce a promise. This is so common in typical async Javascript code, that there is value in removing the need for the remaining boilerplate.

    With async functions, all the remaining boilerplate is removed, leaving only the semantically meaningful code in the program text:

    async function chainAnimationsAsync(elem, animations) {
        let ret = null;
        try {
            for(const anim of animations) {
                ret = await anim(elem);
            }
        } catch(e) { /* ignore and keep going */ }
        return ret;
    }
    
    0 讨论(0)
  • 2020-12-04 04:49

    Is this basically what async/await does under the hood in ESwhatever?

    Not really. It's a different approach for doing sorta the same thing. What async/await turn into is more like

    async function foo() {
      const bar = await Bar();
      bar++;
      const baz = await Baz(bar);
      return baz;
    }
    

    becomes

    function foo() {
      return Bar()
        .then(bar => {
          bar++;
          return Baz(bar)
            .then(baz => {
              return baz;
            });
        });
    }
    
    0 讨论(0)
提交回复
热议问题