在Dropzone.js中混淆函数调用和返回

javascript confusing function calls and returns in Dropzone.js

本文关键字:函数调用 返回 Dropzone js      更新时间:2023-09-26

我正在阅读dropzone.js的代码,其中有一些函数调用对我来说完全没有意义。我需要一些解释。我从_processThumbnailQueue

开始

这里是对createThumnail()的回调调用。1)为什么回调调用是这种直接调用本身的形式。这个函数的内容代表什么?他们遵守这里的关闭规则了吗?

简单地说,这里的调用和返回完全是混乱的…我迷路了,不知道传递了什么,返回了什么。

Dropzone.prototype._processThumbnailQueue = function() {
  if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
    return;
  }
  this._processingThumbnail = true;
  return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {
    return function() {
      _this._processingThumbnail = false;
      return _this._processThumbnailQueue();
    };
  })(this));
};
Dropzone.prototype.createThumbnail = function(file, callback) {
  var fileReader;
  fileReader = new FileReader;
  fileReader.onload = (function(_this) {
    return function() {
      if (file.type === "image/svg+xml") {
        _this.emit("thumbnail", file, fileReader.result);
        if (callback != null) {
          callback();
        }
        return;
      }
      return _this.createThumbnailFromUrl(file, fileReader.result, callback);
    };
  })(this);
  return fileReader.readAsDataURL(file);
};
Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback) {
  var img;
  img = document.createElement("img");
  img.onload = (function(_this) {
    return function() {
      var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;
      file.width = img.width;
      file.height = img.height;
      resizeInfo = _this.options.resize.call(_this, file);
      if (resizeInfo.trgWidth == null) {
        resizeInfo.trgWidth = resizeInfo.optWidth;
      }
      if (resizeInfo.trgHeight == null) {
        resizeInfo.trgHeight = resizeInfo.optHeight;
      }
      canvas = document.createElement("canvas");
      ctx = canvas.getContext("2d");
      canvas.width = resizeInfo.trgWidth;
      canvas.height = resizeInfo.trgHeight;
      drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
      thumbnail = canvas.toDataURL("image/png");
      _this.emit("thumbnail", file, thumbnail);
      if (callback != null) {
        return callback();
      }
    };
  })(this);
  if (callback != null) {
    img.onerror = callback;
  }
  return img.src = imageUrl;
};

我真的不喜欢Dropzone代码的编写方式。

是的,它使用了闭包,但是它以一种非常笨拙和混乱的方式设置了闭包。没有必要立即执行所有这些函数表达式,代码在this_this之间切换的方式是一个混乱的处方。

我快速重写了代码以消除所有这些复杂性。我还没有测试过这个,但我相信它应该做同样的事情。看看这是否更容易理解:

Dropzone.prototype._processThumbnailQueue = function() {
  var dz = this;
  if (dz._processingThumbnail || dz._thumbnailQueue.length === 0) {
    return;
  }
  dz._processingThumbnail = true;
  return dz.createThumbnail(dz._thumbnailQueue.shift(), function() {
    dz._processingThumbnail = false;
    return dz._processThumbnailQueue();
  });
};
Dropzone.prototype.createThumbnail = function(file, callback) {
  var dz = this;
  var fileReader;
  fileReader = new FileReader;
  fileReader.onload = function() {
    if (file.type !== "image/svg+xml") {
      return dz.createThumbnailFromUrl(file, fileReader.result, callback);
    }
    dz.emit("thumbnail", file, fileReader.result);
    if (callback != null) {
      callback();
    }
  };
  return fileReader.readAsDataURL(file);
};
Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback) {
  var dz = this;
  var img;
  img = document.createElement("img");
  img.onload = function() {
    var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;
    file.width = img.width;
    file.height = img.height;
    resizeInfo = dz.options.resize.call(dz, file);
    if (resizeInfo.trgWidth == null) {
      resizeInfo.trgWidth = resizeInfo.optWidth;
    }
    if (resizeInfo.trgHeight == null) {
      resizeInfo.trgHeight = resizeInfo.optHeight;
    }
    canvas = document.createElement("canvas");
    ctx = canvas.getContext("2d");
    canvas.width = resizeInfo.trgWidth;
    canvas.height = resizeInfo.trgHeight;
    drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
    thumbnail = canvas.toDataURL("image/png");
    dz.emit("thumbnail", file, thumbnail);
    if (callback != null) {
      return callback();
    }
  };
  if (callback != null) {
    img.onerror = callback;
  }
  return img.src = imageUrl;
};

可以看到,在每个函数开始时,我将dz设置为this,然后在函数的其余部分始终使用dz。这就是利用闭包所需要做的一切。

另一种简化是将if (file.type !== "image/svg+xml") ...语句的意义颠倒到createThumbnail()中。这消除了整个嵌套层,使代码更容易遵循。