Можно подождать, а потом смешаться в одной реализации? - PullRequest
0 голосов
/ 07 февраля 2019

Мне интересно, можно ли использовать 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);
    }
  }
});
},

Затем я вызываю эту функцию в другой, где я сохраняю объект в indexedDb со ссылкой, полученной из imgur API.

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 (без конструктора обещаний), данные добавлялись в БД до того, как было разрешено обещание; / То, что я не хотел (возможно, я где-то допустил ошибку .. idk).

Мой вопрос заключается в том, является ли приведенный выше код правильным способом сделать это (он работает как задумано), или мне следует его реорганизовать?Если так, пожалуйста, скажите мне, как.Этот вопрос для меня скорее информативен, чем связан с конкретной проблемой.Спасибо.

1 Ответ

0 голосов
/ 07 февраля 2019

Да, вы можете использовать синтаксис mix await и then - они оба работают с обещаниями - но вы не должны делать это в одной и той же функции .

Но этоне главная проблема в вашем коде.Проблема заключается в использовании конструктора Promise antipattern в функции uploadImageToImgur.Не используйте async function s в качестве обратных вызовов.Не создавайте обещания в then обратных вызовах без return их - ваш код не уловит отклонения response.json().

Да, вам понадобится конструктор Promise для обещания читатель, но это все.Выделите это внутри своей собственной функции, чтобы вы не вводили себя в искушение.Это 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 respnse = 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;
  }
},
...