【问题标题】:jquery .done() still runs before deferred.resolve()jquery .done() 仍然在 deferred.resolve() 之前运行
【发布时间】:2019-09-10 14:55:53
【问题描述】:

我已经阅读了关于这个主题的几个问题,但我仍然看不出有什么问题。我有两个函数,一个从文件初始化图像并读取其尺寸,将它们设置为对象的变量。第二个检查尺寸是否在限制范围内。

功能:

  checkDimensions: function() {
      console.log('entering chekDimensions');
      if (options.maxDimensionsWH > 0) {

        console.log(this.checkWidth);
        console.log(this.checkHeight);
        if ((this.checkWidth <= options.maxDimensionsWH || this.checkHeight <= options.maxDimensionsWH)
             && (this.checkWidth > 0 && this.checkHeight > 0)) {
            console.log('returning true');
            return true;    
        } else {
            console.log('returning false');
            return false;
        }

    } else {
        return true;
    }
  },
  initializeCheckImage: function(file) {
    console.log('entering initialization');
    var d = $.Deferred();
    var reader = new FileReader();
      reader.onload = function (e) {
        var img = new Image;
        img.onload = function() {
          this.checkWidth = img.width;
          this.checkHeight = img.height;
          console.log('initializing the image');
          console.log(this.checkWidth);
          console.log(this.checkHeight);
          d.resolve();
        };
        console.log('assigning reader.result');
        img.src = reader.result;
      };
      console.log('assigning a file to the reader');
      reader.readAsDataURL(file);
      console.log('returning deferred');
      return d.promise();
  }

以及它们的名称:

this.initializeCheckImage(file).done(check = this.checkDimensions());

从控制台可以清楚地看到,第二个函数的执行发生在调用d.resolve(); 之前。

> 21:13:34.460 entering initialization
> 21:13:34.461 assigning a file to the reader
> 21:13:34.462 returning deferred
> 21:13:34.462 entering chekDimensions
> 21:13:34.462 0
> 21:13:34.463 0
> 21:13:34.463 chekDimensions returning false
> 21:13:34.478 assigning reader.result
> 21:13:34.493 initializing the image
> 21:13:34.494 30
> 21:13:34.494 30

我做错了什么?谢谢!

【问题讨论】:

  • .done(check = this.checkDimensions()); 您正在立即调用checkDimensions,将其返回值分配给check,并将该返回值作为Promise 回调传递给done

标签: jquery jquery-deferred


【解决方案1】:

promise 函数正在被立即调用:

this.initializeCheckImage(file).done(check = this.checkDimensions());

done 函数应接受 executer 作为参数:

使用参数 resolve 和 reject 传递的函数。这 executor 函数由 Promise 立即执行 实现,传递解析和拒绝函数(执行者是 在 Promise 构造函数之前调用,甚至返回创建的 对象)。

所以它应该只是函数的引用,注意当你用 checkDimensions() 调用它时,JS 会立即执行函数。

所以你需要用函数引用来包装它,但问题是函数的上下文已经改变,checkDimensions() 不再存在于新的上下文中。

为了保留维度变量上下文,您可以从 img.onload 内部调用 checkDimensions 函数:

if (checkDimensions(img.width, img.height)) {
    return d.resolve();; 
}
else {
    return d.reject("Wrong dimensions");
}

this.initializeCheckImage(file)
    .then(() => console.log("RESOLVED"))
    .catch(() => console.log("REJECTED"));

编辑:

为了保持所需对象的上下文,您可以使用绑定,使用 bind()。

var readerOnload = function(e) {
    //code
}

reader.onload = readerOnload.bind(this);

或与:

var self = this;

reader.onload = function() {
    //you can use self
}

在您的情况下,您必须再次为imgOnload 执行此操作。

【讨论】:

  • 我也遇到了上下文的问题。但这意味着,在img.onload 内部,我也脱离了上下文。所以我必须将函数移出对象。它带来了一些新问题,但感谢您为我指出正确的方向
【解决方案2】:

我建议将值传递给解决并在完成时接收。

  checkDimensions: function(dimensions) {
      console.log('entering chekDimensions');
      if (options.maxDimensionsWH > 0) {

        console.log(dimensions.width);
        console.log(dimensions.height);
        if ((dimensions.width <= options.maxDimensionsWH || dimensions.height <= options.maxDimensionsWH)
             && (dimensions.width > 0 && dimensions.height > 0)) {
            console.log('returning true');
            return true;    
        } else {
            console.log('returning false');
            return false;
        }

    } else {
        return true;
    }
  },
  initializeCheckImage: function(file) {
    console.log('entering initialization');
    var d = $.Deferred();
    var reader = new FileReader();
      reader.onload = function (e) {
        var img = new Image;
        img.onload = function() {
          this.checkWidth = img.width;
          this.checkHeight = img.height;
          console.log('initializing the image');
          console.log(this.checkWidth);
          console.log(this.checkHeight);
          d.resolve(
          {
             width:img.width,
             height:img.height
          });
        };
        console.log('assigning reader.result');
        img.src = reader.result;
      };
      console.log('assigning a file to the reader');
      reader.readAsDataURL(file);
      console.log('returning deferred');
      return d.promise();
  }

然后

this.initializeCheckImage(file).done(function(dimensions) 
{ 
check = this.checkDimensions(dimensions) 
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-06
    • 2011-10-30
    • 2014-09-17
    相关资源
    最近更新 更多