Reputation: 8189
I'm not optimistic there's a way to do this, but I wanted to put the question out there. The situation: I'm writing a JavaScript game engine that's tailored for novice programmers. I want the primary scripting interface to be as simple and accessible as possible. Ideally, scripts would end up looking something like this:
this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000, sync: true });
this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
In this scenario, the first backdrop would fade in completely over the course of one second, then the second backdrop would fade in synchronously. The problem? JavaScript will try to execute the second command before the first has completed.
Now, the right way to handle this would be to use promises. Something like:
this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000 }).then(() => {
this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
});
Which is totally an option. (In fact, it's probably what I'll have to settle for.) But there are two reasons why I'd prefer not to go this route. First, it adds a lot of extra verbiage to what is meant to be a simple script. I'd like this to look unintimidating to new programmers, and all those nested functions are gonna start looking scary. Secondly, promises don't handle control flow super well. Even something as simple as an if-then statement will get gnarly.
What I'd really like is some way to do this:
this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000, sync: true });
waitUntilAllPromisesAreResolved();
this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
But that's a pipedream, isn't it? If you can think of a way to make that real, I'd love to hear it.
Upvotes: 1
Views: 607
Reputation: 664196
it adds a lot of extra verbiage to what is meant to be a simple script. I'd like this to look unintimidating to new programmers, and all those nested functions are gonna start looking scary.
Hm, it's much better than a script where this is done by magic (which certainly possible, see below). Most newbies will be able to figure out what then
does, but they won't be able to recognise magic - and are totally confused when something doesn't work then.
Btw, you should almost never have to nest functions when using promises over callbacks, as promises form a flat chain.
Secondly, promises don't handle control flow super well. Even something as simple as an if-then statement will get gnarly.
They do it better than most other options imo. See this example of a simple if-statement.
What I'd really like is some way to do this:
this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000, sync: true }); waitUntilAllPromisesAreResolved(); this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
But that's a pipedream, isn't it?
Not necessarily - there are generators and eventually there will be async/await. Those allow you to use "synchronous" (normal) control-flow statements in asynchronous functions:
(async function() {
await this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000});
await this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
console.log("both done");
}()); // returns a promise
You'll have to use an ES6/ES7 transpiler for these, though.
However, even a simple
this.backdrop('backdrop-1.png', { effect: 'fade-in', duration: 1000, sync: true });
this.backdrop('backdrop-2.png', { effect: 'fade-in', duration: 500 });
where the second effect is animated after the first is very possible today! You just have to put an internal queue of animations on this
, to which the backdrop
method adds instead of executing immediately. jQuery does use this approach for example, and it's very popular!
Upvotes: 2