【问题标题】:Resolve promise into addEventListener将 promise 解析为 addEventListener
【发布时间】:2017-08-10 12:34:18
【问题描述】:

我实际上正在开发一个文本编辑器,只是遇到了一个关于图像上传和显示方法的问题。

我正在努力实现的目标

单击工具栏中的按钮时,应用程序会显示一个用于上传图片的弹出窗口。然后,用户可以通过他的文件系统拖放文件或单击并选择文件。选择图像后,我通过 ajax 将其发送到服务器,该服务器将其上传并存储在文件夹中。完成此操作后,服务器会发送一个响应,表明该文件正常并可以使用。然后该函数解析,编辑器将正确的链接添加到图像。

我尝试了一些在 Promise 中附加事件侦听器时有效的方法。

function uploadImage(editor) {
  /* Displays the pop-up */
  uploadView.style.display = "block";

  var promise = new Promise(function(resolve, reject) {

    uploadInput.addEventListener('change', function(event) {
      /* ajax call */
      resolve(value);
    });
    dropZone.addEventListener('drop', function(event) {
      /* ajax call */
      resolve(value);
    });

  });

  promise.then(function(result) {
    /* Adds the link */
  }, function(err) {
    /* handles errors */
  });
}

这一切都很好,但是每次触发该函数时,都会附加一个新的侦听器,并且每次新单击时内部的函数都会运行一次...

然后我想我可能会在承诺解决后删除侦听器。但是,为了这样做,我不能使用匿名函数,但是我不能在内部使用我的 resolve 方法,因为它会引发错误。

这不起作用:

function uploadImage(editor) {
  /* Displays the pop-up */
  uploadView.style.display = "block";

  var promise = new Promise(function(resolve, reject) {

    uploadInput.addEventListener('change', handleUpload);
    dropZone.addEventListener('drop', handleUpload);

  });

  promise.then(function(result) {
    /* Adds the link */
    /* Removes the listeners */
    uploadInput.removeEventListener('change', handleUpload);
    dropZone.removeEventListener('drop', handleUpload);

  }, function(err) {
    /* Handles errors */
    /* Removes the listeners */
    uploadInput.removeEventListener('change', handleUpload);
    dropZone.removeEventListener('drop', handleUpload);
  });
}

function handleUpload(event) {
  if (event.type == "change") {
    /* ajax call */
    resolve(value); // Throws an error
  } else {
    /* ajax call */
    resolve(value); // Throws an error
  }
}

我想不通了...

【问题讨论】:

  • 我可以在这里看到另一个问题,如果弹出窗口打开并且用户上传,然后更改文件或 dropZone 两次然后事件将触发两次,它将尝试在第二次尝试解决已解决的承诺.

标签: javascript promise


【解决方案1】:

为了这样做,我不能使用匿名函数,但是我不能在里面使用我的解析方法

在命名函数或将它们转换为声明时,没有理由将函数移到 uploadImage 函数或 new Promise 回调之外:

var promise = new Promise(function(resolve, reject) {
  function handleUpload(event) {
    /* Removes the listeners */
    uploadInput.removeEventListener('change', handleUpload);
    dropZone.removeEventListener('drop', handleUpload);
    resolve(event); // works just fine
  }
  uploadInput.addEventListener('change', handleUpload);
  dropZone.addEventListener('drop', handleUpload);
});

promise.then(function(event) {
  if (event.type == "change") {
    return /* ajax call */
  } else {
    return /* other ajax call */
  }
}).then(function(result) {
  /* Adds the link */
}, function(err) {
  /* Handles errors */
});

【讨论】:

  • 在同一个 promise 上链接多个 .then() 方法是否常见?以前从未见过。我试试看。
  • 运行流畅!谢谢你。
  • @PierreBurton 它不会将它们链接到相同的promise,而是将其链接到promise.then(…) 返回的承诺(通过ajax 结果解析)。是的,这很常见。
  • 有关Promise.then(...) 链接的更多信息,请参阅:javascript.info/promise-chaining
【解决方案2】:

ElementTarget.addEventListener() 接受三个参数。事件名称、回调和选项对象。现在这个选项对象很有趣并且很方便,因为它包含一个名为once 的布尔属性。它有什么作用..?

  • once:一个布尔值,指示在添加后最多应调用一次侦听器。如果为 true,则在调用时会自动删除侦听器。

酷。然后你可以简单地改变你的第一个 sn-p 如下;

function uploadImage(editor) {
  /* Displays the pop-up */
  uploadView.style.display = "block";

  var promise = new Promise(function(resolve, reject) {

    uploadInput.addEventListener('change', function(event) {
      /* ajax call */
      resolve(value);
    },{once: true}); // remove event after run once
    dropZone.addEventListener('drop', function(event) {
      /* ajax call */
      resolve(value);
    },{once: true}); // remove event after run once

  });

  promise.then(function(result) {
    /* Adds the link */
  }, function(err) {
    /* handles errors */
  });
}

【讨论】:

  • 听起来很有趣。一定要看看这个!
猜你喜欢
  • 2021-08-03
  • 1970-01-01
  • 2016-04-14
  • 2017-11-20
  • 2017-05-31
  • 2017-11-30
  • 2017-05-22
  • 2020-06-27
  • 1970-01-01
相关资源
最近更新 更多