【问题标题】:Waiting for promises in different methods用不同的方法等待承诺
【发布时间】:2014-04-17 23:35:53
【问题描述】:

我目前正在为承诺而苦苦挣扎,我认为我的概念有点错误。基本上我想做的是编写一个小模板处理程序。

它有一个 load() 方法,它加载一个模板并将其存储到一个属性中,它将是可链接的。我想要链接它的方法是attachTo(),将我之前加载的模板附加到一个DOM元素。

由于模板是异步加载的,我尝试使用 Promise。但似乎 Promise 上的 done() 方法正在立即触发,并且在异步调用完成之前。

我这样称呼它:

tpl.load('stuff.html').attachTo($('.someElement'));

我希望它的行为是,每当我调用 attachTo() 时,它都会等待我之前调用的 load() 方法完成异步操作,然后触发 done 方法中提供的回调。

这是处理程序的相关部分

var tpl = {
...
    template: null,
    promise: null,

    load: function(template) {
        this.promise = $.get(this.templateUrl + template, function(response){
            this.template = response;
            console.log(this.template);
            //Outputs the desired value
        });
        return this;
    },

    attachTo: function(el) {
        var self = this;
        $.when(this.promise).done(function(){
            //outputs null but should output the 
            //value that has been set in my async call
            console.log(self.template);
        });
    }

..
}

tpl.load('stuff.html').attachTo($('.someElement'));

【问题讨论】:

  • 这看起来还不错,也许你收到一个错误(无论结果类型如何都会调用done)。尝试使用 this.promise.then().fail() 方法来区分好的请求结果和坏的请求结果。
  • 感谢@PeterAronZentai。确实是我的错。当我设置模板属性时,我弄乱了范围。这不再指代我的对象,而是指回调的范围。只需要使用代理。感谢您指出这个问题!
  • 我不确定您的代码有什么问题目前需要澄清一下吗?
  • @BenjaminGruenbaum 已经解决了,请参阅我上面的评论 :) 但可以肯定。问题是我认为在处理我的load() 方法中的异步请求之前,我认为promise 上的done() 方法已被触发,因为我的template 属性是空的,尽管它应该由加载中的ajax 请求填充方法。最终结果证明这只是一个范围界定问题,与 deferred 无关。
  • 如果它已经解决了 - 而不是编辑它,请将问题恢复到原始状态并发布关于您如何解决它的答案。

标签: javascript jquery promise jquery-deferred deferred


【解决方案1】:

虽然您自己已经发现了问题,但建议的解决方案并不是一个好的解决方案。

您不应使用在某个时候设置的全局变量,而应仅将 Promise 用于传播更改,但 Promise 应表示这些值。这会带来更好的函数式编程风格。

在你的情况下:

var tpl = {
    …
    templatePromise: null,
    load: function(template) {
        this.templatePromise = $.get(this.templateUrl + template).then(function(response) {
            console.log(this.template);
            //Outputs the desired value
            return response;
        });
        return this;
    },
    attachTo: function(el) {
        $.when(this.templatePromise).done(function(template) {
            // get the template here:              ^^^^^^^^
            console.log(template);
        });
    }
    …
}

【讨论】:

    【解决方案2】:

    原来这是一个范围界定问题。延迟并没有什么问题,但我为其分配了值的实例的范围。

    load: function(template) {
        this.promise = $.get(this.templateUrl + template, function(response){
            this.template = response;
            console.log(this.template);
            //Outputs the desired value
        });
        return this;
    },
    

    在这里,我为this.template 分配了一个值。但是我不在我的对象范围内,而是在$.get() 方法的闭包范围内。因此,其他方法无法将值从属性中提取出来,因为它从未存储在那里。

    我想出了:

    load: function(template) {
        var self = this;
        this.promise = $.get(this.templateUrl + template, function(response){
            self.template = response;
        });
        return this;
    },
    

    我首先将对象实例实例分配给self 变量,并在闭包内引用它而不是使用this。为了更优雅地解决它,还可以使用$.proxy()

    就是这样。这只是一个范围界定,而不是一个延迟问题。

    【讨论】:

      猜你喜欢
      • 2019-04-29
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 2021-08-29
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 2018-03-19
      相关资源
      最近更新 更多