尝试在NodeJS中从ejs.renderFile获取html时返回未定义的返回值

时间:2020-06-29 09:05:26

标签: node.js asynchronous async-await

我正在尝试从HTML生成屏幕截图

async function makeWeeklyReport(meterId, week) {
    // get meters from meter
    const meter = meters.find(it => it.prm === meterId);
    const weeklyData = await generateWeeklyGraph(meter, week);
    ejs.renderFile(path.join(__dirname, './views/partials/', "weekly_graph.ejs"), {
    }, (err, data) => {
        if (err) {
            console.log(err)
            return
        }
        console.log(data); // Actually printing good value
        return data
    });
}

当我调用此函数时:

data = await makeWeeklyReport(meterId, week)
console.log("generated WeeklyReport", data) // returns undefined

数据为undefined

但是当我在console.log(data);中执行makeWeeklyReport()时,它实际上会打印html。

我认为await关键字应该等待异步功能结束。

我已经尝试放置:

res.render(view, {.., async:true, ... }...) 

但它不起作用

我应该如何解决?

2 个答案:

答案 0 :(得分:0)

ejs.renderFile不是异步函数/不返回承诺,并且在完成渲染后将调用传递的回调函数。由于您无法直接从回调中返回值,因此rhis无法正常工作。

但是,您可以将调用包装在Promise中并解决它,一旦调用了回调(请注意,如果发生错误,我是rejecting Promise,则可以更改此设置,{{ 1}}在这种情况下也应如此):

resolve

然后您可以等待此功能并处理解析的值:

async function makeWeeklyReport(meterId, week) {
    const meter = meters.find(it => it.prm === meterId);
    const weeklyData = await generateWeeklyGraph(meter, week);
    return new Promise((resolve, reject) => {
        // get meters from meter

        ejs.renderFile(path.join(__dirname, './views/partials/', "weekly_graph.ejs"), {}, (err, data) => {
            if (err) {
                console.log(err)
                return reject(err);
            }
            console.log(data); // Actually printing good value
            resolve(data);
        });
    });
}

答案 1 :(得分:0)

这与async / await无关。

您的return语句位于回调函数中,因此您的makeWeeklyReport函数未返回任何内容。

您可以使用Promise来取消包装回调值。

async function makeWeeklyReport(meterId, week) {
    // get meters from meter
    const meter = meters.find(it => it.prm === meterId);
    const weeklyData = await generateWeeklyGraph(meter, week);

    const [err, data] = await new Promise(resolve => {
        const p = path.join(__dirname, './views/partials/', "weekly_graph.ejs");
        ejs.renderFile(p, { }, (err, data) => resolve([err, data]);
    });

    if (err) {
        console.log(err);
        return;
    }
    console.log(data); // Actually printing good value
    return data;
}

为提高可读性,您甚至可以将renderFile包装为async函数:

function renderFileAsync(path, data) {
    return new Promise(resolve => ejs.renderFile(path, data,
        (err, data) => resolve([err, data]));
}

然后您的makeWeeklyReport函数可以这样写:

async function makeWeeklyReport(meterId, week) {
    // get meters from meter
    const meter = meters.find(it => it.prm === meterId);
    const weeklyData = await generateWeeklyGraph(meter, week);

    const p = path.join(__dirname, './views/partials/', "weekly_graph.ejs");
    const [err, data] = await renderFileAsync(p, { });

    if (err) {
        throw err;
    }

    return data;
}