在 qooxdoo 应用程序中使用 Promises

Using Promises in a qooxdoo application

在一个qooxdoo class中,我有一组异步方法需要链接(序列化):

main: function() {
    async1();
},

async1: function() {
    var json = new qx.data.store.Json("http://...");
    json.addListener("loaded", function(event) {
        ...
        async2();
    });
},

async2: function() {
    // similar to async1
}

随着步骤数量的增加,链条变得难以追踪,代码变得不可读。我们可以做的是使用 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
}

这很好用,但只有在我们添加一些真正的逻辑之前。请记住,它是一个 qooxdoo class,其中包含很多内容 this。但突然发现,在 then() 和 catch() 中使用的 async* 方法和匿名函数都将它们的 this 上下文绑定到 window,一个全局对象。为了能够使用实际的 this,我们可以执行重新绑定:

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.async1 实例方法时,为什么 this 没有隐式绑定?

如果在顶部添加 var self = this;,在所有函数中,您可以通过调用 self:

来引用对象本身
main: function() {
    var self = this;
    new Promise(self.async1)
    .then(function() {
        return new Promise(self.async2);
    }).then(function() {
        return new Promise(self.async3);
    }).catch(...);
},

勾选this answer out

基本上,从根本上看,你并没有做错什么。这就是上下文应该如何工作的。您真正需要的是针对您的特定用例的一些语法糖。您可以自己制作这些糖扩展或使用库来完成一些繁重的工作。

您还可以像 Danbopes 建议的那样重组您的代码并对其进行组织,这样您就可以减少内联绑定。这将使您更好地阅读流程。