嵌套异步函数的问题(异步系列中的异步瀑布)

Problems with nested async functions (async waterfall in async series)

请提供一些帮助,我是 nodejs 的新手,这是一个常见问题,我尝试了此处其他帖子中的示例。我在最后一个函数中遇到问题。

我正在尝试:

  1. 检查 data.json 是否存在并使用 async.waterfall
  2. 的一些数据创建它

function IfDataDontExistsCreate(callback)
{
    async.waterfall([ //If data dont exists
        function IfExistDataFile(callback) {
            fs.exists(path, function(exists){
                if(!exists)
                {
                    try {
                        const firstDataFile = {"readedPosts":{"id": []}};
                        const json = JSON.stringify(firstDataFile, null, 2);
                        callback(null, json);
                    } catch (error) {
                        callback(error);
                    }
                    
                }
            }
        )},
        function CreateDataFile(json ,callback) {
            fs.writeFile(path, json, function (err) {
                if(err) callback(err);
            })
        }
    ], function (err, callback) {
        if(err) throw err;
    });

    callback(null, callback);
}

  1. 读取 data.json、获取数据、添加一些信息并用 async.waterfall
  2. 保存 data.json

function AppendtoDataFile(info, callback)
{
    async.waterfall([
        function ReadGetData(callback) {
            fs.readFile(path, (err, data) => {
                if(err) throw err;
                let datajson = JSON.parse(data.toString());
                datajson.readedPosts.id.push(info.toString()); //Add info
                callback(err, datajson)
            })
        },
        function WriteDataFile(data, callback) {
            const writeData = fs.writeFile(path, JSON.stringify(data, null, 2), function (err) {
                if(err) throw err;
                callback(err);
            })
        }
    ], function(err, callback)
    {
        if(err) throw err;
    });

    callback(null, callback);
}

  1. 加入async.series
  2. 的函数

function AddPostID(postID, callback)
{
    async.series({
        one: function (callback) {
            IfDataDontExistsCreate(function () {
                callback(null, "DataFile Created");
            });
        },
        two: function (callback) {
            AppendtoDataFile(postID, function () {
                callback(null, "PostID added to Datafile");
            });
        }
    }),
    function (err, results) {
        if(error) throw err;
        console.log(results);
    }
}

我不确定您面临的确切问题,但我确实在您的代码中发现了一个问题。 IfDataDontExistsCreateAppendtoDataFile 函数中的 callback 在异步瀑布完成执行之前被调用。

从 async.waterfall 的最终回调中调用 callback(err, null) 并从两个函数中删除最后一行,即 callback(null, callback) 应该可以解决问题。

由于@Raeesaa 已经回答了您的具体问题, 我提供了一种使用 promises 和 async/await 的替代方法,使代码更具可读性和简洁性

首先,您可以避免 fs.exists 使用带有 wx 标志的 fs.writeFile

'wx' - Like 'w' but fails if the path exists.


'use strict';

const fs = require('fs');
const { promisify } = require('util');

const writeFile = promisify(fs.writeFile);
const readFile = promisify(fs.readFile);

const path = '/tmp/foo.json';

async function IfDataDontExistsCreate() {
    const firstDataFile = {
        readedPosts: {
            id: []
        }
    };

    const json = JSON.stringify(firstDataFile, null, 2);

    try {

        await writeFile(path, json, { flag: 'wx' });
    } catch(e) {
        // If EEXIST means the file is already created, do nothing
        if(e.code !== 'EEXIST')
            throw e;
    }
}

async function AppendtoDataFile(info) {

    const data = await readFile(path, 'utf8');

    let datajson = JSON.parse(data);
    datajson.readedPosts.id.push(info.toString()); // Add info

    return writeFile(path, JSON.stringify(datajson, null, 2));
}

async function AddPostID(postID) {

    // Wait until the file is created
    await IfDataDontExistsCreate();
    console.log('DataFile Created');

    // We append after the file has been created
    await AppendtoDataFile(postID);
    console.log('PostID added to Datafile');

    return true;
}

AddPostID(5)
  .then(res => console.log('Done!'))
  .catch(err => console.error(err));