Javascript 创建异步函数以稍后在express route中调用结果
我必须通过API从Box.com获取一个Excel文件,并将Excel转换为JSON。稍后将使用Express和Handlebar呈现此JSON 我创建了以下函数来获取Excel/JSON:Javascript 创建异步函数以稍后在express route中调用结果,javascript,express,async-await,Javascript,Express,Async Await,我必须通过API从Box.com获取一个Excel文件,并将Excel转换为JSON。稍后将使用Express和Handlebar呈现此JSON 我创建了以下函数来获取Excel/JSON: let getExternalFile = async () => { const stream = await client.files.getReadStream('123456789'); const external = await fs.createWriteStream('/ext
let getExternalFile = async () => {
const stream = await client.files.getReadStream('123456789');
const external = await fs.createWriteStream('/external.xlsx');
stream.pipe(external);
let finished = await external.on('finish', async () => {
const excel = await excelToJson({
source: fs.readFileSync(external.path),
header: {
rows: 1
},
columnToKey: {
A: "edate",
B: "esource"
},
sheets: ['Sheet1']
});
console.log(excel);
return excel
})
}
我现在的问题是,当我这样做时,我不知道如何解决悬而未决的承诺:
let testData = getExternalFile();
console.log(testData); // Promise { <pending> }
我必须用匿名异步函数来调用它吗?
async
/wait
并不是所有异步事物的灵丹妙药。他们被设计成只履行承诺。具体来说,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
}
所有非承诺函数(我不会称它们为非“异步”,因为它会混淆异步函数和非异步函数之间的区别,因为人们有时使用“异步”表示异步,有时表示“异步”关键字,这是承诺生成函数)。。。我离题了。。。所有非承诺函数都不能与wait
一起使用。这包括事件发射器x.on('some_event'…)
对于这种情况,您需要将它们包装在newpromise()
中,以将它们转换为承诺
现在我们已经编写了上述函数,我们可以简单地等待结果:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile(); // use await here!!
// ...
});
app.get('/',async/*{
让testData=await getExternalFile();//在此处使用await!!
// ...
});
如果有多个等待,则功能可能较慢:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile();
let testData2 = await getExternalFile2(); // SLOW!
// ...
});
app.get('/',async/*{
让testData=等待getExternalFile();
让testData2=等待getExternalFile2();//慢!
// ...
});
如果您能顺利完成,您可以并行执行异步函数:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testDataArray = await Promise.all([
getExternalFile(), getExternalFile2() // FAST!
]);
// ...
});
app.get('/',async/*{
让testDataArray=wait Promise.all([
getExternalFile(),getExternalFile2()//快!
]);
// ...
});
Epologue:错误 在实际代码中,您应该捕获等待的代码上的错误,以防止服务器崩溃:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
try {
let testData = await getExternalFile(); // use await here!!
// ...
}
catch (err) {
// ...
}
});
app.get('/',async/*{
试一试{
让testData=await getExternalFile();//在此处使用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
}
所有非承诺函数(我不会称它们为非“异步”,因为它会混淆异步函数和非异步函数之间的区别,因为人们有时使用“异步”表示异步,有时表示“异步”关键字,这是承诺生成函数)。。。我离题了。。。所有非承诺函数都不能与wait
一起使用。这包括事件发射器x.on('some_event'…)
对于这种情况,您需要将它们包装在newpromise()
中,以将它们转换为承诺
现在我们已经编写了上述函数,我们可以简单地等待结果:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile(); // use await here!!
// ...
});
app.get('/',async/*{
让testData=await getExternalFile();//在此处使用await!!
// ...
});
如果有多个等待,则功能可能较慢:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testData = await getExternalFile();
let testData2 = await getExternalFile2(); // SLOW!
// ...
});
app.get('/',async/*{
让testData=等待getExternalFile();
让testData2=等待getExternalFile2();//慢!
// ...
});
如果您能顺利完成,您可以并行执行异步函数:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
let testDataArray = await Promise.all([
getExternalFile(), getExternalFile2() // FAST!
]);
// ...
});
app.get('/',async/*{
让testDataArray=wait Promise.all([
getExternalFile(),getExternalFile2()//快!
]);
// ...
});
Epologue:错误 在实际代码中,您应该捕获等待的代码上的错误,以防止服务器崩溃:
app.get('/', async /* <--IMPORTANT */ (req, res) => {
try {
let testData = await getExternalFile(); // use await here!!
// ...
}
catch (err) {
// ...
}
});
app.get('/',async/*{
试一试{
让testData=await getExternalFile();//在此处使用await!!
// ...
}
捕捉(错误){
// ...
}
});
或者,您可以使用一个中间件,例如捕获异步错误。如果它是一个返回的承诺,您不能添加
。然后()
并在那里添加您的代码吗?您已经在使用async/await,所以也要等待这个承诺wait getExternalFile()
@mrks您没有从getExternalFile()
返回任何内容,我认为如果您有多个承诺,可以将它们存储在一个数组中并使用Promise.all()
等待所有问题解决。您还需要返回finished
变量。在外部范围中定义并返回excel
。如果是返回的承诺,您不能添加。然后()
并在那里添加代码吗?您已经在使用async/wait,所以也要等待这个承诺wait getExternalFile()
@mrks您没有从getExternalFile()
返回任何内容,我认为如果您有多个承诺,可以将它们存储在一个数组中并使用Promise.all()
等待所有问题解决。您还需要返回finished
变量。在外部范围中定义并返回excel
。很好!别忘了处理快速路线中的错误callbacks@ArturKhrabrov是的,我真的应该试试。。抓住积木或使用承诺抓住中间环节!别忘了处理快速路线中的错误callbacks@ArturKhrabrov是的,我真的应该试试。。捕获块或使用承诺捕获中间件