从使用事件对象

时间:2017-04-23 10:11:09

标签: javascript html5 callback filereader

我差不多把这个理论搞砸了,但是我对这些细节感到困惑。给定var $data(更改后文件输入的event object)的图像大小调整函数将返回var dataurl返回(dataurl {{ 1}})。

我的问题是让jpeg认识到它是在嵌套函数中更新的。正如我在下面显示的那样,代码将dataurl记录到控制台,显示data:image/jpg;base64未更新。

研究让我发现这是由于异步调用,这是有道理的。在继续并打印到控制台之前,var没有及时更改。我还了解到,这是发布dataurl以更新var。

的标准情况

在尝试这样做之后,我找不到使用callback更新var的干净(或工作)方法。在我显示当前代码后,我将对此进行扩展:

callback

这是现在的代码,正在找出如何拉出function clProcessImages($data) { var filesToUpload = $data.target.files; var file = filesToUpload[0]; var canvas = document.createElement('canvas'); var dataurl = 'data:image/jpg;base64'; var img = document.createElement("img"); var reader = new FileReader(); reader.onload = function(e, callback) { img.onload = function () { var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0); var MAX_WIDTH = 800; var MAX_HEIGHT = 600; var width = img.width; var height = img.height; if (width > height) { if (width > MAX_WIDTH) { height *= MAX_WIDTH / width; width = MAX_WIDTH; } } else { if (height > MAX_HEIGHT) { width *= MAX_HEIGHT / height; height = MAX_HEIGHT; } } canvas.width = width; canvas.height = height; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, width, height); dataurl = canvas.toDataURL("image/jpeg",0.8); callback(dataurl); } img.src = e.target.result } reader.readAsDataURL(file); console.log(dataurl); // console log mentioned in question return dataurl; }; 的中间位置。我知道在显示的状态下不会调用回调。

我的第一个障碍是我(貌似)以后无法再次调用callback函数,因为它似乎是一个特别是在加载对象时被触发的事件,而不是手动调用的事件。随时。我最好的猜测是创建一个reader.onload将触发的新函数,它将包含所有当前reader.onload函数,我可以稍后直接指定,以发出reader.onload,跳过引用callback事件。

看起来像一个合理的理论,但后来我陷入了onload函数通过的event object。假设我应用上述理论,onload事件调用新函数onload。它将通过readerOnLoad(e)罚款。但是,如果想要稍后执行回调,我怎么能手动调用event object,因为我没有看到以优雅的方式从同一readerOnLoad(e)传递event object的方法。感觉有点像我正在陷入非常混乱的代码*来解决,而感觉应该有一些更优雅的东西,对于一种不太感兴趣的情况。

*原始FileReader $data变量是通过在文件输入检测到更改时存储全局变量获得的。理论上,我可以创建一个全局变量来存储event object onload的event object。它只是感觉非常复杂,因为我的原始代码和以这种方式运行的代码之间的差异是相当严重和不优雅的,唯一的区别是更新未及时准备好的var。

1 个答案:

答案 0 :(得分:2)

使用异步函数时,通常需要将函数作为回调传递。你可以使用这样的NodeJS样式回调:

// asyncTask is an asynchronous function that takes 3 arguments, the last one being a callback

asyncTask(arg1, arg2, function(err, result) {
  if (err) return handleError(err);
  handleResult(result);
})

所以在你的情况下,你可以这样做:

clProcessImages($data, function(dataurl) {
  console.log(dataurl);
  // Do you other thing here
});

function clProcessImages($data, onProcessedCallback) {
  var filesToUpload = $data.target.files;
  var file = filesToUpload[0];
  var canvas = document.createElement('canvas');
  var dataurl = 'data:image/jpg;base64';

  var img = document.createElement("img");

  var reader = new FileReader();
  reader.onload = function(e) {

    img.onload = function () {

      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0);

      var MAX_WIDTH = 800;
      var MAX_HEIGHT = 600;
      var width = img.width;
      var height = img.height;

      if (width > height) {
        if (width > MAX_WIDTH) {
          height *= MAX_WIDTH / width;
          width = MAX_WIDTH;
        }
      } else {
        if (height > MAX_HEIGHT) {
          width *= MAX_HEIGHT / height;
          height = MAX_HEIGHT;
        }
      }
      canvas.width = width;
      canvas.height = height;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, width, height);
      dataurl = canvas.toDataURL("image/jpeg",0.8);
      onProcessedCallback(dataurl);

    }
    img.src = e.target.result

  }
  reader.readAsDataURL(file);

  return dataurl;
};

您可能还想将错误对象传递给回调,就像第一个示例一样,并正确处理它。

简而言之,总是将回调函数作为参数添加到您自己的异步函数中。