嵌套异步函数的问题(异步系列中的异步瀑布)
Problems with nested async functions (async waterfall in async series)
请提供一些帮助,我是 nodejs 的新手,这是一个常见问题,我尝试了此处其他帖子中的示例。我在最后一个函数中遇到问题。
我正在尝试:
- 检查 data.json 是否存在并使用 async.waterfall
的一些数据创建它
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);
}
- 读取 data.json、获取数据、添加一些信息并用 async.waterfall
保存 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);
}
- 加入async.series
的函数
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);
}
}
我不确定您面临的确切问题,但我确实在您的代码中发现了一个问题。 IfDataDontExistsCreate
和 AppendtoDataFile
函数中的 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));
请提供一些帮助,我是 nodejs 的新手,这是一个常见问题,我尝试了此处其他帖子中的示例。我在最后一个函数中遇到问题。
我正在尝试:
- 检查 data.json 是否存在并使用 async.waterfall 的一些数据创建它
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);
}
- 读取 data.json、获取数据、添加一些信息并用 async.waterfall 保存 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);
}
- 加入async.series 的函数
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);
}
}
我不确定您面临的确切问题,但我确实在您的代码中发现了一个问题。 IfDataDontExistsCreate
和 AppendtoDataFile
函数中的 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));