开发者问题收集

使用 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