Home > Software engineering >  Render image data in ejs with nodejs
Render image data in ejs with nodejs

Time:05-10

I have a nodejs express system, and want to render an image of a qr code datablock.

I am generating the image from my mongoose Schema

BaseUserSchema.methods.getProvisionImage = function getProvisionImage() {
    qr.toDataURL( JSON.stringify({
        account: this.accountName,
        code: this.provisionCode,
    }),
    {},
    function (err, url) {

        if (err) throw err;

        return url;
    });
};

and want to draw in an image on the page

<img 
     src="<% provisionUser.getProvisionImage() %>"
     title="Click to enlarge" >

The provisionUser is correct, and the value at the end of the generation code when I am debugging is

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAK ... [etc]  ... ==

This all looks pretty good to me - how do I convert that string into something that an can display?

CodePudding user response:

Since ejs does not support asynchronous functions with callback your only way to get around it might be to use async/await.

You can try this:

BaseUserSchema.methods.getProvisionImage = async function getProvisionImage() {
    var data = '';
    try {
        data = await qr.toDataURL(JSON.stringify({
            account: this.accountName,
            code: this.provisionCode,
        }));
    } catch (e) {}
    return data;
};

And to explain why you code can't work:

// the getProvisionImage function does not return anything
// since you do not have a return statement in the getProvisionImage scope
BaseUserSchema.methods.getProvisionImage = function getProvisionImage() {
    qr.toDataURL( JSON.stringify({
        account: this.accountName,
        code: this.provisionCode,
    }),
    {},
    function callback(err, url) { // this function is the scope of the return statement bellow

        if (err) throw err;
        // this will return a value to the caller of this function
        // not the caller of getProvisionImage
        return url;
    });
    
    // this return will work, not the above one in the callback function
    return 'data:image/png;bas....';
};

CodePudding user response:

try promisifying the method, and then await the result into a variable which will be passed to ejs:

BaseUserSchema.methods.getProvisionImage = function getProvisionImage() {

    return new Promise((resolve, reject) => {
    
        qr.toDataURL(JSON.stringify({
                account: this.accountName,
                code: this.provisionCode,
            }), {},
            function(err, url) {

                if (err) reject(err);

                resolve(url);
            });
    });
};

//...

const img = await provisionUser.getProvisionImage();

//...
src="<% img %>"
  • Related