3
\$\begingroup\$

Often I end up with

var askName = () => {
    return new Promise((resolve, reject) => {
        this.waitForInput('Name:').then(name => {
            this.ask('Are there more players?', ['Yes', 'No']).then(answer => {
                if(answer === 'yes') {
                    askName().then(resolve);
                } else {
                    resolve();
                }
            });
        });
    });
};
askName();

when I need to chain promises. Now, in ES7 it will be possible to write this as

var morePlayers = true;
while(moreUsers){
    var name = await this.waitForInput('Name:');
    var morePlayers = (await this.ask('Are there more players?', ['Yes', 'No'])) === 'yes';
}

which is of course beautiful, but how can this be written as neatly as possible supporting the most recent versions of Chrome and Firefox (and probably Edge as well)?

\$\endgroup\$
  • \$\begingroup\$ @Quill Thanks, it's the weirdest typo I always end up making... I have no idea why \$\endgroup\$ – David Mulder Feb 7 '16 at 14:32
  • \$\begingroup\$ And @the 2 downvoters, it would be absolutely great if you guys would explain your reasoning ;-) . \$\endgroup\$ – David Mulder Feb 7 '16 at 15:07
  • \$\begingroup\$ You probably mean ES7 rather than ES6. OTH, the reason for the downvotes (not me) is probably that this does not quite seem relevant for codereview.SE. Stackoverflow maybe? \$\endgroup\$ – jcaron Feb 7 '16 at 15:25
  • \$\begingroup\$ @jcaron You were right about ES7 (which also explains why browsers don't implement it yet :( ), and this would be off-topic as opinion-based on SO as I am asking about 'best practices and design pattern usage'. \$\endgroup\$ – David Mulder Feb 7 '16 at 15:32
1
\$\begingroup\$

You can use generators to bring the code down to a form that's almost as small and readable as if using async.

doAsync(function* () {
  var morePlayers = true;
  while (moreUsers) { // assuming morePlayers
    var name = yield this.waitForInput('Name:');
    var morePlayers = (yield this.ask('Are there more players?', ['Yes', 'No'])) === 'yes';
  }
})

Why does this work? Every time the generator function yields it gives control back to the doAsync function. This function unwraps waits until the promise resolved, gets its result and plugs it back in the generator through the same yield it ceased control earlier.

\$\endgroup\$
  • \$\begingroup\$ This might be an incredibly stupid question, but how is doAsync defined here? I have quite little experience with generators, but I haven't seen anybody use a return value for yield before, so I am a bit confused. \$\endgroup\$ – David Mulder Feb 7 '16 at 15:04
  • \$\begingroup\$ @DavidMulder generators have a next method which can optionally take a parameter - this optional parameter becomes the result of the yield expression. Generators also have a throw method which you can use in the same way to pass on the reason of a rejected promise. \$\endgroup\$ – adrianton3 Feb 7 '16 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.