async
/ await
не является панацеей для всех вещей асинхронных. Они были предназначены для работы только с Обещаниями. В частности, async
/ await
не работает с источниками событий. Правильная реализация getExternalFile
должна быть:
let getExternalFile = async () => {
const stream = client.files.getReadStream('123456789'); // no await here
const external = fs.createWriteStream('/external.xlsx'); // no await here
stream.pipe(external);
let finished = new Promise ((resolve, reject) => {
external.on('finish', async () => { // cannot use await here
const excel = await excelToJson({
source: fs.readFileSync(external.path),
header: {
rows: 1
},
columnToKey: {
A: "edate",
B: "esource"
},
sheets: ['Sheet1']
});
console.log(excel);
resolve(excel);
})
});
return finished; // return the promise so you can await it later
}
Все не обещающие функции (я не буду называть их не «асинхронными», потому что это будет путать людей с разницей между асинхронными асинхронными функциями и неасинхронными асинхронными функциями, потому что люди иногда используют «асинхронный» для обозначения асинхронных, а иногда и для имею в виду ключевое слово "async", которое является функциями, генерирующими обещания) ... Я отвлекся ... все функции без обещаний не работают с await
. Это включает в себя такие вещи, как источники событий x.on('some_event' ... )
.
В таких случаях вам нужно будет обернуть их в new Promise()
, чтобы преобразовать их в Обещания.
Теперь, когда мы переписали вышеуказанную функцию, мы можем просто дождаться результата:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile(); // use await here!!
// ...
});
Если у вас несколько ожиданий, функция может работать медленно:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile();
let testData2 = await getExternalFile2(); // SLOW!
// ...
});
Если вам это удастся, вы можете параллельно выполнять асинхронные функции:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testDataArray = await Promise.all([
getExternalFile(), getExternalFile2() // FAST!
]);
// ...
});
Эполог: Ошибки
В реальном коде вы должны отлавливать ошибки в коде, который вы ожидаете, чтобы предотвратить сбой вашего сервера:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
try {
let testData = await getExternalFile(); // use await here!!
// ...
}
catch (err) {
// ...
}
});
В качестве альтернативы вы можете использовать промежуточное ПО, такое как express-async-handler , для перехвата асинхронных ошибок.