node.js 异步迭代时的数据一致性
node.js data consistency when iterating asynchronously
我有一个工具,基本思路如下:
//get a bunch of couchdb databases. this is an array
const jsonFile = require('jsonfile');
let dbList = getDbList();
const filePath = 'some/path/to/file';
const changesObject = {};
//iterate the db list. do asynchronous stuff on each iteration
dbList.forEach(function(db){
let merchantDb = nano.use(db);
//get some changes from the database. validate inside callback
merchantDb.get("_changes", function(err,changes){
validateChanges(changes);
changesObject['db'] = changes.someAttribute;
//write changes to file
jsonFile.writeFile(filePath, changesObject, function (err) {
if (err) {
logger.error("Unable to write to file: ");
}
});
})
const validateChanges = function(changes) {
if (!validateLogic(changes) sendAlertMail();
}
为了提高性能,迭代不是同步完成的。因此在'parallel'中可以有多次迭代运行。我的问题是这会导致任何数据不一致 and/or 文件写入过程有任何问题吗?
编辑:
每次迭代都会写入相同的文件。
编辑:2
更改存储为具有键值对的 JSON 对象。关键是数据库名称。
如果你真的在写一个 单个 文件,你看起来是(虽然很难确定),那么不;你有一个竞争条件,其中多个回调可能会同时尝试写入同一个文件(请记住,I/O 不会在 Node 中的 JavaScript 线程上完成,除非你使用 *Sync
函数),这最多意味着最后一个获胜,最坏的情况下意味着 I/O 由于重叠而导致的错误。
如果您要为每个 db
编写单独的文件,那么前提是 validateChanges
、validateLogic
、sendAlertMail
之间没有串扰(共享状态)等应该没问题
仅供参考:它将启动任务(作业)获取更改,然后将其写出;对 get
的调用的回调将不会是 运行 直到稍后所有这些作业都排队时。
您正在循环中创建闭包,但您这样做的方式没问题,因为您是在 forEach
回调中进行的,而且您没有使用 db
在 get
回调中(对于 forEach
回调会很好,但对于您可能循环数组的其他一些方式则不行)。如果您有兴趣,请在 this question's answers 中查看有关这方面的详细信息。
但这条线是可疑的:
let merchantDb = nano.use('db');
我怀疑你的意思是(没有引号):
let merchantDb = nano.use(db);
对于它的价值,从问题的更新和您的各种评论来看,更好的解决方案是 而不是 每次单独写出文件。相反,您想收集更改然后将它们写出来。
您可以像这样使用您正在使用的经典节点回调 API 来做到这一点:
let completed = 0;
//iterate the db list. do asynchronous stuff on each iteration
dbList.forEach(function(db) {
let merchantDb = nano.use(db);
//get some changes from the database. validate inside callback
merchantDb.get("_changes", function(err, changes) {
if (err) {
// Deal with the fact there was an error (don't return)
} else {
validateChanges(changes);
changesObject[db] = changes.someAttribute; // <=== NOTE: This line had 'db' rather than db, I assume that was meant to be just db
}
if (++completed === dbList.length) {
// All done, write changes to file
jsonFile.writeFile(filePath, changesObject, function(err) {
if (err) {
logger.error("Unable to write to file: ");
}
});
}
})
});
我有一个工具,基本思路如下:
//get a bunch of couchdb databases. this is an array
const jsonFile = require('jsonfile');
let dbList = getDbList();
const filePath = 'some/path/to/file';
const changesObject = {};
//iterate the db list. do asynchronous stuff on each iteration
dbList.forEach(function(db){
let merchantDb = nano.use(db);
//get some changes from the database. validate inside callback
merchantDb.get("_changes", function(err,changes){
validateChanges(changes);
changesObject['db'] = changes.someAttribute;
//write changes to file
jsonFile.writeFile(filePath, changesObject, function (err) {
if (err) {
logger.error("Unable to write to file: ");
}
});
})
const validateChanges = function(changes) {
if (!validateLogic(changes) sendAlertMail();
}
为了提高性能,迭代不是同步完成的。因此在'parallel'中可以有多次迭代运行。我的问题是这会导致任何数据不一致 and/or 文件写入过程有任何问题吗?
编辑: 每次迭代都会写入相同的文件。
编辑:2 更改存储为具有键值对的 JSON 对象。关键是数据库名称。
如果你真的在写一个 单个 文件,你看起来是(虽然很难确定),那么不;你有一个竞争条件,其中多个回调可能会同时尝试写入同一个文件(请记住,I/O 不会在 Node 中的 JavaScript 线程上完成,除非你使用 *Sync
函数),这最多意味着最后一个获胜,最坏的情况下意味着 I/O 由于重叠而导致的错误。
如果您要为每个 db
编写单独的文件,那么前提是 validateChanges
、validateLogic
、sendAlertMail
之间没有串扰(共享状态)等应该没问题
仅供参考:它将启动任务(作业)获取更改,然后将其写出;对 get
的调用的回调将不会是 运行 直到稍后所有这些作业都排队时。
您正在循环中创建闭包,但您这样做的方式没问题,因为您是在 forEach
回调中进行的,而且您没有使用 db
在 get
回调中(对于 forEach
回调会很好,但对于您可能循环数组的其他一些方式则不行)。如果您有兴趣,请在 this question's answers 中查看有关这方面的详细信息。
但这条线是可疑的:
let merchantDb = nano.use('db');
我怀疑你的意思是(没有引号):
let merchantDb = nano.use(db);
对于它的价值,从问题的更新和您的各种评论来看,更好的解决方案是 而不是 每次单独写出文件。相反,您想收集更改然后将它们写出来。
您可以像这样使用您正在使用的经典节点回调 API 来做到这一点:
let completed = 0;
//iterate the db list. do asynchronous stuff on each iteration
dbList.forEach(function(db) {
let merchantDb = nano.use(db);
//get some changes from the database. validate inside callback
merchantDb.get("_changes", function(err, changes) {
if (err) {
// Deal with the fact there was an error (don't return)
} else {
validateChanges(changes);
changesObject[db] = changes.someAttribute; // <=== NOTE: This line had 'db' rather than db, I assume that was meant to be just db
}
if (++completed === dbList.length) {
// All done, write changes to file
jsonFile.writeFile(filePath, changesObject, function(err) {
if (err) {
logger.error("Unable to write to file: ");
}
});
}
})
});