使用 Express 时,Await 关键字不会等待 NodeJS 中的承诺实现
2021-06-24
547
我是 javascript 和异步函数的新手,我正在尝试使用 Express 在 NodeJs 中编写一个 API,该 API 从 Postman 获取 JPG 图像并将其放入我的图像分类机器学习模型(改编自 MobileNet)中进行预测。图像需要先进行预处理,然后才能进入模型。我使用包 resize-optimize-images get-image-data 来调整大小并将图像更改为适合我的模型的格式。
const app = express();
const multer = require('multer');
const tf = require('@tensorflow/tfjs-node');
const image = require('get-image-data');
const resizeOptimizeImages = require('resize-optimize-images');
let model;
(async function () {
model = await tf.loadLayersModel("http://localhost:5000/model/model.json");
})();
app.post('/classify', upload.single('file'), (req, res) => {
//call methods to resize and preprocess the image
resize();
var input = preprocess();
//have model predict
console.log(input);
let prediction = model.predict(input);
});
这是我的调整大小函数代码。
function resize() {
(async () => {
// Set the options.
const options = {
images: [imagePath],
width: 224,
height: 224,
quality: 90
};
// Run the module.
await resizeOptimizeImages(options);
console.log("resized");
})();
}
这是我的预处理函数代码。
function preprocess() {
image(imagePath, async (err, imageData) => {
// pre-process image
const numChannels = 3;
const numPixels = imageData.width * imageData.height;
const values = new Int32Array(numPixels * numChannels);
const pixels = imageData.data;
for (let i = 0; i < numPixels; i++) {
for (let channel = 0; channel < numChannels; ++channel) {
values[i * numChannels + channel] = pixels[i * 4 + channel];
}
}
const outShape = [imageData.height, imageData.width, numChannels];
const input = tf.tensor3d(values, outShape, 'float32');
console.log(input);
return input;
});
当我运行程序时,我在调用预测的行中收到错误“TypeError:无法读取未定义的属性‘length’”。 resize 和 preprocess 函数未完全执行,导致输入到 predict 中未定义。我以为,通过在 resizeImageOptimizer() 中放置 await,程序会等待该过程完成后再继续。然而,它似乎是在最后执行此操作,尽管它是先调用的。 如能帮助解决此问题,我将不胜感激。
2个回答
好的,请尝试像这样使用 async await
const resize = async () => {
const options = {
images: [imagePath],
width: 224,
height: 224,
quality: 90
};
// Run the module.
await resizeOptimizeImages(options);
console.log("resized");
}
此外,您还必须传递 async 函数:
app.post('/classify', upload.single('file'), async (req, res) => {
//call methods to resize and preprocess the image
await resize();
var input = await preprocess();
//have model predict
console.log(input);
let prediction = model.predict(input)
})
请记住,async/await 仅适用于 Promises,因此您的函数(如
preprocess()
)也必须返回 Promise:
const preprocess = () => {
return new Promise((resolve) => {
image(imagePath, (err, imageData) => {
// pre-process image
const numChannels = 3;
const numPixels = imageData.width * imageData.height;
const values = new Int32Array(numPixels * numChannels);
const pixels = imageData.data;
for (let i = 0; i < numPixels; i++) {
for (let channel = 0; channel < numChannels; ++channel) {
values[i * numChannels + channel] = pixels[i * 4 + channel];
}
}
const outShape = [imageData.height, imageData.width, numChannels];
const input = tf.tensor3d(values, outShape, 'float32');
console.log(input);
resolve(input);
});
})
}
Nikita Mazur
2021-06-24
您不必将其放入箭头函数中,只需使主函数
async
即可,同时在
let
中创建
option
对象,因为
const
用于常量值,但您提供的是动态
imagepath
async function resize() {
// Set the options.
let options = {
images: [imagePath],
width: 224,
height: 224,
quality: 90
};
// Run the module.
await resizeOptimizeImages(options);
console.log("resized");
}
此外,您也可以将
async await
放在路由中,但这是可选的:
app.post('/classify', upload.single('file'), async (req, res) => {
//call methods to resize and preprocess the image
let resize = await resize();
var input = preprocess();
//have model predict
console.log(input);
let prediction = model.predict(input);
});
iftikharyk
2021-06-24