jquery .done () по-прежнему выполняется перед deferred.resolve () - PullRequest
0 голосов
/ 20 апреля 2019

Я прочитал несколько вопросов здесь на эту тему, и я все еще не вижу, что не так.У меня есть две функции, одна инициализирует изображение из файла и считывает его размеры, устанавливая их в качестве переменных объекта.Второй проверяет, находятся ли размеры в допустимых пределах.

Функции:

  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

Что я делаю не так?Спасибо!

Ответы [ 2 ]

1 голос
/ 20 апреля 2019

Функция обещания вызывается немедленно:

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

Функция done должна принимать в качестве параметра executer:

Функция, переданная с аргументами, разрешает и отклоняет. Функция executor выполняется немедленно Promise реализация, передача функций разрешения и отклонения (исполнитель вызывается до того, как конструктор Promise даже возвращает созданное объект).

Так что это должна быть только ссылка для работы, обратите внимание, что когда вы вызываете ее с помощью checkDimensions (), JS немедленно выполняет функцию.

Таким образом, вам потребуется заключить его в ссылку на функцию, но проблема в том, что контекст функции изменился и checkDimensions() больше не существует в новом контексте.

Чтобы сохранить контекст переменной измерения, вы можете вызвать функцию checkDimensions из img.onload с помощью:

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"));

Edit:

Чтобы сохранить контекст требуемого объекта, вы можете использовать связывание с bind ().

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

reader.onload = readerOnload.bind(this);

Или с:

var self = this;

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

В вашем случае придется сделать это еще раз для imgOnload.

0 голосов
/ 20 апреля 2019

Я бы посоветовал передать значение для разрешения и получения после завершения.

  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) 
});
...