如何使用util promisify使用Async等待?

时间:2019-08-28 08:30:31

标签: node.js asynchronous promise

我想对fs.accessfs.unlink使用异步等待。这两个函数都返回一个错误,没有结果回调。因此问题在于,如果函数抛出错误,它将直接进入catch块并继续进行下一次迭代。

const unlink = util.promisify(fs.unlink);
const access = util.promisify(fs.access);

const deleteAssetsCtrl = async (req, res) => {
    try {
        let iteration = 0;
        for (let file of fileUrls) {
            const fileUrl = file.fileUrl
            const fileLocation = path.resolve(contentFolderPath, fileUrl);
            access(fileLocation); // step 1
            unlink(fileLocation); // step 2
            const deleteRowQuery = `DELETE FROM table WHERE fileUrl = '${fileUrl}'`;
            executeQuery(deleteRowQuery); // step 3

        if (fileUrls.length == iteration){
            res.send("true");
        } else {
            res.send('false')
        }           
    } catch (error) {
        console.log('Error =>', error);
        res.send(error);
    }
}
Error => Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
     

如何控制流量。 (步骤应按顺序进行)

3 个答案:

答案 0 :(得分:3)

您需要在每个异步函数(基本上,所有返回诺言的函数)上添加await注释

const unlink = util.promisify(fs.unlink);
const access = util.promisify(fs.access);

const deleteAssetsCtrl = async (req, res) => {
    try {
        let iteration = 0;
        for (let file of fileUrls) {
            const fileUrl = file.fileUrl
            const fileLocation = path.resolve(contentFolderPath, fileUrl);
            await access(fileLocation); // step 1
            await unlink(fileLocation); // step 2
            const deleteRowQuery = `DELETE FROM table WHERE fileUrl = '${fileUrl}'`;
            executeQuery(deleteRowQuery); // step 3

        if (fileUrls.length == iteration){
            res.send("true");
        } else {
            res.send('false')
        }           
    } catch (error) {
        console.log('Error =>', error);
        res.send(error);
    }
}

这意味着您使用util.promisify或任何其他方法包装在promise中的所有内容都会创建一个 async 功能,您可以await进行此操作。

如果您需要从函数本身返回的值,则只有在await函数的情况下,才可以访问返回值的内容,因为如果没有该关键字,则节点将继续执行并赢得在继续操作之前,不要等待值返回或异步函数完成。

答案 1 :(得分:2)

您必须将await放在每个承诺的函数之前。

你可以试试吗:

const unlink = util.promisify(fs.unlink);
const access = util.promisify(fs.access);

const deleteAssetsCtrl = async (req, res) => {
    try {
        let iteration = 0;
        for (let file of fileUrls) {
            const fileUrl = file.fileUrl
            const fileLocation = path.resolve(contentFolderPath, fileUrl);
            await access(fileLocation);
            await unlink(fileLocation);
            const deleteRowQuery = `DELETE FROM table WHERE fileUrl = '${fileUrl}'`;
            executeQuery(deleteRowQuery); 

        if (fileUrls.length == iteration){
            res.send("true");
        } else {
            res.send('false')
        }           
    } catch (error) {
        console.log('Error =>', error);
        res.send(error);
    }
}

编辑:您可能需要在函数await上使用executeQuery并可能对其进行赋值……executeQuery是异步还是同步的?

答案 2 :(得分:1)

承诺只会将功能转换为承诺。您应该使用unlink, access with await,await将等待,直到该诺言得以解决。

注意:您可能还需要对executeQuery使用await,因为这是异步操作取决于它是否返回promise。

函数内的任何地方迭代都不会增加。

const unlink = util.promisify(fs.unlink);
const access = util.promisify(fs.access);

const deleteAssetsCtrl = async (req, res) => {
    try {
        let iteration = 0;
        for (let file of fileUrls) {
            const fileUrl = file.fileUrl
            const fileLocation = path.resolve(contentFolderPath, fileUrl);
            await access(fileLocation); // step 1
            await unlink(fileLocation); // step 2
            const deleteRowQuery = `DELETE FROM table WHERE fileUrl = '${fileUrl}'`;
            await executeQuery(deleteRowQuery); // step 3 
        } // is it closed correctly
        if (fileUrls.length == iteration){
            res.send("true");
        } else {
            res.send('false')
        }           
    } catch (error) {
        console.log('Error =>', error);
        res.send(error);
    }
}