Node.js调用AWS Rekognition返回undefined 如何正确获取异步返回值
问题原因
- 你遇到的是Node.js异步调用的典型执行顺序问题:
AWS.Rekognition.detectLabels是异步回调API,你传入的回调函数会在云服务返回结果后才执行,而原有imageReko函数没有等待异步结果就直接结束运行,也没有返回有效数值,所以你拿到的返回值默认为undefined,同步的打印逻辑也会先于异步回调执行,才会出现你看到的日志顺序。 - 你后续修改的写法有两个问题:一是
imageReko本身没有返回Promise对象,await根本无法感知到异步执行状态;二是调用async函数时没有加await,拿到的只会是Pending状态的Promise对象,不是实际的标签数据。
修复步骤
第一步:改造imageReko为Promise风格
将原有回调逻辑包裹在Promise实例中,成功时返回标签数据,失败时抛出错误:
// Load the SDK and UUID var AWS = require('aws-sdk'); var uuid = require('node-uuid'); const imageReko = (img) =>{ // 这里返回Promise实例 return new Promise((resolve, reject) => { const bucket = 'image-for-reko1' // the bucketname without s3:// var string = img.split("/"); const photo = string[2] // the name of file const config = new AWS.Config({ accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, region: process.env.AWS_REGION }) AWS.config.update({ region: 'eu-west-2' }); const client = new AWS.Rekognition(); const params = { Image: { S3Object: { Bucket: bucket, Name: photo }, }, MaxLabels: 3, MinConfidence: 85 } client.detectLabels(params, function(err, response) { if (err) { console.log(err, err.stack); // 出错时抛出错误 reject(err) } else { console.log(`Detected labels for: ${photo}`) console.log("the data in side the file"); console.log(response.Labels); // 成功时返回标签数据 resolve(response.Labels) } }); }) } module.exports = imageReko;
第二步:改造调用逻辑,用async/await等待异步结果
注意await只能在被async关键字修饰的函数内部使用,所以你需要先给路由处理函数加上async标识,同时加上错误捕获逻辑:
// 注意路由处理函数前面加了async app.post('/posts', async (req, res) => { if (req.body.act === "post") { var imgLabels if(req.body.img){ console.log("here is the file called"); try { // 加await等待异步结果返回 imgLabels = await imageReko(req.body.img) console.log("here is the data after return function"); console.log(imgLabels); // 这里就可以执行存数据库的逻辑了 // 例如:await db.save({labels: imgLabels, ...其他字段}) } catch (err) { // 捕获调用Rekognition可能出现的错误,返回给前端 return res.status(500).send({msg: '图像识别失败', error: err.message}) } } // 后续其他逻辑 res.send({status: 'success', labels: imgLabels}) } })
执行逻辑说明
- 改造后的
imageReko返回Promise对象,await关键字会暂停当前函数执行,直到Promise状态变为resolved(成功)才会继续执行后续代码,拿到的imgLabels就是你需要的标签数组。 - 增加
try/catch是为了捕获云服务调用失败、网络错误等异常情况,避免服务无响应崩溃。
内容的提问来源于stack exchange,提问作者Zeyad Alaa Eldin
相关产品推荐
相关产品推荐

