2

I need to proces some data. I can do it in sync and async way like this (simplified):

  1. sync way:

    for (var i in input) {
        result += input[i]
    }
    
  2. async way

    function f(input,cb) {
      var result;
      if (!input) {
        setTimeout(function() {cb(result)},500);
      } else {
        f(input.slice(1),function(r) {
          result+=input[0];
        });
      }
    }
    

Is it possible to rewrite async code using generators? I wish I had some For loop code instead of recursion.

deceze
  • 510,633
  • 85
  • 743
  • 889
user2106769
  • 445
  • 5
  • 15
  • 2
    What are you trying to achieve? I don't see a point in processing this data in asynchronous way, unless it takes a lot of time and you don't want to block the event loop. Also, in this example you could just use the `.join()` method: `result = input.join('');`. – Michał Perłakowski Jun 08 '17 at 15:32
  • 1
    By the way, your async code using callbacks is overcomplex. Doing input.slice(1) at each iteration is not a performant way... – Jonas Wilms Jun 08 '17 at 15:34
  • 1
    @Michał Perłakowski. yeah, It is just an example. In reality, I'm fetching data asynchronously from Internet, I have no input[] array. I want to process async data but to avoid recursive callbacks - is it possible? – user2106769 Jun 08 '17 at 15:37
  • 1
    @user2106769 Yes, it's possible. Read about promises and async functions. But we can't help you without having some more specific example of your code. – Michał Perłakowski Jun 08 '17 at 15:42
  • _"Is it possible to rewrite async code using generators? I wish I had some For loop code instead of recursion."_ What is actual issue with code at Question? – guest271314 Jun 08 '17 at 16:24
  • @user2106769 if you think the existing answer works, can you mark this question as answered? if not, can you tell us what you want? – mikemaccana Jun 09 '17 at 18:24
  • Although this question predates the other, appears to be a duplicate of https://stackoverflow.com/questions/48101479/javascript-async-generator/52900682#52900682 – Doug Coburn Oct 20 '18 at 00:02

1 Answers1

0

Using await (a newer ES2017 technology that is built on generators in ES6), and assuming, as you've said:

  • you have multiple items (in this case ['apple', 'peach', 'banana'])
  • you wish to perform some async operation on them
  • You wish to avoid callbacks and .then() (which is a good idea if you're on node 7+ or current browsers)

Then:

var doThing = async function (input) {
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve(`Result for ${input}`)
        }, 2000);
    });
}


var start = async function(listOfThings){
    var result = await Promise.all(listOfThings.map(doThing))
    console.log('All done', result)
}

start(['apple', 'peach', 'banana'])

Will return:

All done [ 'Result for apple', 'Result for peach', 'Result for banana' ]

To get some data from the network instead, you can simply replace the the setTimeout with superagent or (if you want to write your own query string encoding, URL handling etc) fetch.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • `async`/`await` does not use generators. It uses similar mechanisms, but is in no way based on them. – Bergi Jun 08 '17 at 16:13
  • Thanks @bergi. I've edited my answer to clarify and add a reference to Eich's statement re: generators and await. – mikemaccana Jun 08 '17 at 16:18
  • Why is `aync/await` usage necessary where `javascript` at Answer includes use of `Promise` constructor and `Promise.all()`? – guest271314 Jun 08 '17 at 16:25
  • See [Implementing coroutine control flow in JavaScript](https://stackoverflow.com/questions/43547606/implementing-coroutine-control-flow-in-javascript/43547825#43547825) – guest271314 Jun 08 '17 at 16:31
  • @guest271314 because without `await` you'd be using `.then()` and a callback to `.then()` for when the promise is resolved. `await` allows you to resume on the next line in the same style as traditional sync programming - see https://en.wikipedia.org/wiki/Direct_style – mikemaccana Jun 09 '17 at 09:36
  • The patterns are equivalent as to result. It is a matter of preference as to which pattern is utilized, no? – guest271314 Jun 09 '17 at 13:41
  • 1
    @guest271314 No, the `.then()` results in more complex code (it creates additional scopes) and achieves the result with longer code (which is inefficient). – mikemaccana Jun 09 '17 at 18:23
  • @mikemaccana Interesting point about additional scopes. How can we empirically measure and compare the "efficiency" of each approach at https://tc39.github.io/ecmascript-asyncawait/? – guest271314 Jun 09 '17 at 18:38
  • @guest271314 Cognitive overhead normally corresponds to the amount of tokens. Less functions equals less to understand. – mikemaccana Jun 12 '17 at 10:45