Я извлекаю файл Excel из API, и мне нужно прочитать и изменить его с помощью библиотеки xlsx. Я использую node 8.10 и async / await для этого:
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 ('finish', resolve) не выполняет этого? Спасибо за помощь!
Также следует отметить, что я не уверен, будет ли это работать для скачиваний файлов, которые разбиты на части (размер файла неизвестен во время загрузки).
@marzelin, похоже, это сделал! Составьте краткий ответ о том, почему это работает, и я приму это. Спасибо!
@ Сал, что ты имеешь в виду? Я нигде не указываю размер файла и таблица загружается правильно?
Я бы не стал об этом беспокоиться. Вы справитесь с этим, если это когда-нибудь случится :)
Код тут же вызывает 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.info("I log immediately when the page loads and not at click event"))
good.addEventListener("click", () => console.info("I log properly when button is clicked"))
<button>broken button</button>
<button>good button</button>
Но почему в первом примере вызывается метод resolve до завершения работы с конвейером? @marzelin
вроде как ты сразу звонишь
resolve
. попробуйте.on('finish', () => resolve(reportPath))