【问题标题】:Can await and then be mixed in one implementation?可以等待然后混合在一个实现中吗?
【发布时间】:2019-07-01 15:33:04
【问题描述】:

我想知道 await 和 .then 是否可以在同一个异步函数中使用? 这是我的功能:

uploadImageToImgur: async function (file) {
return new Promise(function(resolve, reject) {
  const url = 'https://api.imgur.com/3/image',
  reader  = new FileReader();

  if (file) {
    reader.readAsDataURL(file);
  }

  reader.onloadend = async function () {
    let { result } = reader;

    try {
      const request = await fetch(url, {
        method: 'POST',
        headers: {
          "Authorization": 'my auth',
        },
        body: result.replace(/^data:image\/(png|jpg|jpeg|gif);base64,/, "")
      })
      .then((response) => {
        response.json()
        .then(data => {
          resolve(data.data.link)
        })
      });
    } catch (e) {
      reject(e);
    }
  }
});
},

然后我在另一个函数中调用此函数,在其中我使用从 imgur API 获得的链接将对象保存到 indexedDb。

this.uploadImageToImgur(image)
  .then((image) => {
    let db = this.dbOpen.result,
        tx = db.transaction('EventsStore', 'readwrite'),
        store = tx.objectStore('EventsStore');

    event = store.put({ title, location, description, summary, date, time, image });
    //rest of the code
  });

我为什么选择这种方法?因为当我只使用 await 关键字(没有 promise 构造函数)时,数据会在 promise 被解决之前添加到数据库中;/ 什么不是我想要的(可能我在某个地方犯了一个错误.. idk)。

我的问题是,如果上面的代码是正确的方法(它按预期工作)还是我应该重构它?如果是这样,请告诉我如何。这个问题对我来说信息量很大,而不是与特定问题有关。 谢谢。

【问题讨论】:

  • 您忘记标记语言了。

标签: javascript asynchronous promise async-await


【解决方案1】:

是的,您可以混合使用 awaitthen 语法 - 它们都适用于承诺 - 但 you shouldn't do so in the same function

但这不是您代码中的主要问题。问题在于Promise constructor antipatternuploadImageToImgur 函数中的使用。不要使用async functions 作为回调。不要在没有 return 的情况下在 then 回调中创建承诺 - 拒绝 response.json() 不会被您的代码捕获。

是的,您将需要Promise 构造函数到promisify 读者,但仅此而已。将它分解到它自己的功能中,这样你就不会陷入诱惑。执行器内部的 if (file) 条件导致您的承诺在某些情况下永远无法解决!

清理完毕:

function readDataUrl(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = function() {
      resolve(this.result);
    };
    reader.onerror = reader.onabort = reject; // don't forget this!
    reader.readAsDataURL(file);
  });
}

uploadImageToImgur: async function(file) {
  const url = 'https://api.imgur.com/3/image',
  if (file) {
    const result = await readDataUrl(file);
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        "Authorization": 'my auth',
      },
      body: result.replace(/^data:image\/(png|jpg|jpeg|gif);base64,/, "")
    });
    const data = await response.json();
    return data.data.link;
  }
}

【讨论】:

  • 是否约定将reject 保留为默认实现?
  • @Slaiyer 我不知道“约定”,但是是的,如果可能(并且有用),那么我建议避免将 resolvereject 包装在不必要的额外功能中.在这种情况下,我希望以错误为参数调用onerror 回调,所以这对我来说很有意义。如果您想使用自定义错误/消息来拒绝,当然,请继续使用拒绝该功能的功能。
猜你喜欢
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-04
  • 1970-01-01
  • 2020-03-02
相关资源
最近更新 更多