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?