При извлечении файла из API и его передаче по электронной почте возникает ошибка, когда файл не найден.

1

Я вытаскиваю файл Excel из API, и мне нужно его прочитать и изменить, используя библиотеку xlsx. Я использую узел 8.10 и async/жду этого:

const report = await getVisitorReport(visitorQueryString, 'test12.xls', uri);

let workbook = XLSX.readFile('test12.xls');

И вот функция getVisitorReport. Обратите внимание, что я разрешаю обещание по финишу для трубы:

async function getVisitorReport(queryString, reportPath, uri) {
return new Promise((resolve, reject) => {
request({
  url: uri,
  qs: queryString,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Basic ' + new Buffer(process.env.username + ':' + process.env.password, 'utf8').toString('base64')
  }
}, (error, response, body) => {
  if (error) {
    reject(error);
  } else {
    if (response.statusCode === 200) {
      resolve(body);
    } else if (response.statusCode === 409) {
      setTimeout(() => {
        resolve(getVisitorReport(queryString));
      }, response.headers['Retry-After'] * 1000);
    } else {
      reject(response);
    }
  }
}).pipe(fs.createWriteStream(reportPath)).on('finish', resolve(reportPath));
});
}

Файл вытягивается и создается правильно. Кажется, что вторая строка XLSX.readFile('test12.xls') происходит до того, как файл будет сохранен локально. Что я здесь делаю неправильно? Как я могу убедиться, что файл сохранен, прежде чем пытаться его прочитать? Почему.pipe.on("закончить", разрешить), не выполнив этого? Спасибо за помощь!

  • 0
    Похоже, вы немедленно позвоните resolve . попробуйте .on('finish', () => resolve(reportPath))
  • 0
    Также следует отметить, что я не уверен, сработает ли это для загрузок файлов по частям (размер файла неизвестен во время загрузки).
Показать ещё 3 комментария
Теги:
async-await
asynchronous
xlsx

1 ответ

1
Лучший ответ

Код немедленно вызывает здесь resolve: .on('finish', resolve(reportPath)).

Вы можете либо предоставить функцию решимость непосредственно к on обработчик:

.on('finish', resolve)

Или, если вам нужно передать некоторые данные, используйте функцию стрелки:

.on('finish', () => resolve(args))

редактировать:

если вы сделаете это так: .on('finish', resolve(reportPath)) это примерно равно

resolve(reportPath); // immediately calls resolve which makes a promise resolved 
                     // so await doesn't stop the further code execution
....on('finish', undefined)

Чтобы лучше понять этот пример:

const [bad, good] = document.querySelectorAll("button");

bad.addEventListener("click", console.log("I log immediately when the page loads and not at click event"))

good.addEventListener("click", () => console.log("I log properly when button is clicked"))
<button>broken button</button>
<button>good button</button>
  • 0
    Но почему в первом примере вызывается решимость до завершения конвейера? @marzelin
  • 0
    Большое спасибо за отличное редактирование / объяснение!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню