Promise.all 返回未定义
Promise.all is returning undefined
当我异步映射数组时,Promise.all 应该让函数等待所有承诺都已解决。但是,Promise.all 显示为未定义。这是我的代码。请有人能告诉我我做错了什么吗?谢谢
router.get("/vehicle_reports/interior-pictures", auth, async (req, res) => {
const fileKeysObj = await Report.findOne({ orderId: req.params.jobId }, {
"vehicleInterior": 1
})
const fileKeysArray = fileKeysObj.interior
console.log("fileKeysArray: ", fileKeysArray);
//Retrieve the files from S3
const files = fileKeysArray.map(async (item) => {
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
await s3.getObject(params, async (err, data) => {
if (err) {
throw new Error()
}
else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
return { base64Data, contentType, fileName }
}
})
})
console.log( files) //Pending promise
await Promise.all(files)
console.log( files) //Undefined
res.send(files) //Sends empty array
})
将 map
调用的内部替换为如下所示。
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
return new Promise((res, rej) => {
s3.getObject(params, async (err, data) => {
if (err) {
rej('FAILED');
} else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
res( { base64Data, contentType, fileName });
}
})
});
我希望人们停止炒作 async
/await
。 await
关键字旨在与 Promises 一起使用。并不是所有的异步函数 return promises。许多 API(例如 S3)改用回调。此外,您可以期望 multiple/infinite 数据 return 的架构(例如服务器监听传入连接或读取流)不适合基本上是 single-shot 的 Promises。对于那些EventEmitters更合适。
async
关键字不会将函数转换为 Promise。它执行 return 承诺,但无法将基于回调的函数转换为可与 await
一起使用的承诺。为此,您需要使用原始的 Promise
构造函数。因此,获取promise数组的正确方法如下:
const files = fileKeysArray.map((item) => { /* note: async keyword is useless here */
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
// We are returning a Promise, so no need to force it to further
// return a promise by marking this function as "async" above:
return new Promise((perfectly_fine, oops_something_went_wrong) => {
s3.getObject(params, async (err, data) => {
if (err) {
// Normally people would name this function "reject"
// but I'm illustrating that the name is really up to you
// and is not part of the syntax:
oops_something_went_wrong(err)
}
else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
// This is how you "return" to a promise:
perfectly_fine({ base64Data, contentType, fileName })
}
})
})
})
现在可以等待结果了。但是你用的 await
错了。 await
的正确方法如下:
let resulting_files = await Promise.all(files);
console.log(resulting_files);
您也可以选择不使用 await。相反,您可以使用 .then()
:
Promise.all(files).then(resulting_files => {
// use resulting_files here:
console.log(resulting_files);
});
当我异步映射数组时,Promise.all 应该让函数等待所有承诺都已解决。但是,Promise.all 显示为未定义。这是我的代码。请有人能告诉我我做错了什么吗?谢谢
router.get("/vehicle_reports/interior-pictures", auth, async (req, res) => {
const fileKeysObj = await Report.findOne({ orderId: req.params.jobId }, {
"vehicleInterior": 1
})
const fileKeysArray = fileKeysObj.interior
console.log("fileKeysArray: ", fileKeysArray);
//Retrieve the files from S3
const files = fileKeysArray.map(async (item) => {
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
await s3.getObject(params, async (err, data) => {
if (err) {
throw new Error()
}
else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
return { base64Data, contentType, fileName }
}
})
})
console.log( files) //Pending promise
await Promise.all(files)
console.log( files) //Undefined
res.send(files) //Sends empty array
})
将 map
调用的内部替换为如下所示。
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
return new Promise((res, rej) => {
s3.getObject(params, async (err, data) => {
if (err) {
rej('FAILED');
} else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
res( { base64Data, contentType, fileName });
}
})
});
我希望人们停止炒作 async
/await
。 await
关键字旨在与 Promises 一起使用。并不是所有的异步函数 return promises。许多 API(例如 S3)改用回调。此外,您可以期望 multiple/infinite 数据 return 的架构(例如服务器监听传入连接或读取流)不适合基本上是 single-shot 的 Promises。对于那些EventEmitters更合适。
async
关键字不会将函数转换为 Promise。它执行 return 承诺,但无法将基于回调的函数转换为可与 await
一起使用的承诺。为此,您需要使用原始的 Promise
构造函数。因此,获取promise数组的正确方法如下:
const files = fileKeysArray.map((item) => { /* note: async keyword is useless here */
const params = {
Bucket: process.env.AWS_BUCKET_NAME,
Key: item.fileKey
}
// We are returning a Promise, so no need to force it to further
// return a promise by marking this function as "async" above:
return new Promise((perfectly_fine, oops_something_went_wrong) => {
s3.getObject(params, async (err, data) => {
if (err) {
// Normally people would name this function "reject"
// but I'm illustrating that the name is really up to you
// and is not part of the syntax:
oops_something_went_wrong(err)
}
else {
const base64Data = base64Arraybuffer.encode(data.Body)
const contentType = data.ContentType
const fileName = item.fileName
// This is how you "return" to a promise:
perfectly_fine({ base64Data, contentType, fileName })
}
})
})
})
现在可以等待结果了。但是你用的 await
错了。 await
的正确方法如下:
let resulting_files = await Promise.all(files);
console.log(resulting_files);
您也可以选择不使用 await。相反,您可以使用 .then()
:
Promise.all(files).then(resulting_files => {
// use resulting_files here:
console.log(resulting_files);
});