In a qooxdoo class, I have a set of asynchronous methods that need to be chained (serialized):
main: function() {
async1();
},
async1: function() {
var json = new qx.data.store.Json("http://...");
json.addListener("loaded", function(event) {
...
async2();
});
},
async2: function() {
// similar to async1
}
As the number of the steps grows, the chain becomes hard to trace, and the code gets unreadable. What we can do is rewrite our code using Promises:
main: function() {
new Promise(this.async1)
.then(function() {
return new Promise(this.async2);
}).then(function() {
return new Promise(this.async3);
}).catch(...);
},
async1: function(resolve, reject) {
var json = new qx.data.store.Json("http://...");
json.addListener("loaded", function(event) {
...
resolve();
});
},
async2: function(resolve, reject) {
// similar to async1
}
This works great but only until we add some real logic. Remember it's a qooxdoo class with a lot of stuff encapsulated into this
. But suddenly it turns out that both async* methods and anonymous functions used in then() and catch() have their this
context bound to window
, a global object. To be able to use actual this
, we can perform rebind:
main: function() {
new Promise(this.async1.bind(this))
.then(function() {
this.doSomeStuff();
return new Promise(this.async2.bind(this));
}.bind(this)).then(function() {
return new Promise(this.async3.bind(this));
}.bind(this)).then(function() {
this.doSomeFinalStuff();
}.bind(this)).catch(function() {
this.doStuffOnError();
}.bind(this));
},
async1: function(resolve, reject) {
this.doOtherStuff();
var json = new qx.data.store.Json("http://...");
json.addListener("loaded", function(event) {
...
resolve();
});
}
This finally works, but doh, ugly is the code! Are there any ways to get rid of those manual binds? Why isn't this
implicitly bound when we reference this.async1
, an instance method?
Check this answer out
Basically, it doesn't look like you're doing anything wrong fundamentally. That's how the context is supposed to work. What you really need is some syntax sugar for your specific use case. You can make these sugar extensions yourself or use a library to do some heavy lifting.
You also could restructure your code like Danbopes suggests and organize it so you're doing less inline-binding. This would allow you to read your flow better.