javascript - 异步迭代时的node.js数据一致性

标签 javascript node.js asynchronous concurrency couchdb

我有一个工具,其基本思路如下:

//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();
}

为了提高性能,迭代不是同步完成的。因此,可以“并行”运行多个迭代。我的问题是这会导致任何数据不一致和/或文件写入过程出现任何问题吗?

编辑: 每次迭代都会写入相同的文件。

编辑:2 更改存储为具有键值对的 JSON 对象。键是数据库名称。

最佳答案

如果您真的在写入一个单个 文件,而您看起来确实是(尽管很难确定),那么不;你有一个竞争条件,其中多个回调可能会同时尝试写入同一个文件(请记住,I/O 不会在 Node 中的 JavaScript 线程上完成,除非你使用 *Sync 函数),这最多意味着最后一个获胜,最坏的情况是由于重叠导致 I/O 错误。

如果您要为每个 db 写入单独的文件,则前提是 validateChangesvalidateLogic 之间没有串扰(共享状态) >、sendAlertMail等,应该没问题。

仅供引用:它将启动任务(作业)获取更改,然后将其写出;调用 get 的回调将在所有这些作业都排队后才会运行。

您正在循环中创建闭包,但您这样做的方式没问题,因为您是在 forEach 回调中执行此操作,而且因为您没有使用 db get 回调中(这对于 forEach 回调来说很好,但对于您可能循环数组的其他一些方式则不行)。 this question's answers 中有关这方面的详细信息如果你有兴趣。

不过,这条线是可疑的:

let merchantDb = nano.use('db');

我怀疑你的意思是(没有引号):

let merchantDb = nano.use(db);

对于它的值(value),从问题的更新和您的各种评论来看,更好的解决方案是每次单独写出文件。相反,您想收集更改,然后将它们写出来。

您可以像这样使用您正在使用的经典 Node 回调 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: ");
                }
            });
        }
    })
});

关于javascript - 异步迭代时的node.js数据一致性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47532838/

相关文章:

javascript - “this”并不引用它被调用的上下文(对于箭头函数)

javascript - onclick AJAX POST 请求(由于某种原因获取 GET)

node.js - 如何测量使用 socket.io 内部传输的数据大小

javascript - 有条件地包含没有 document.write 的 JS 文件

events - 异步和事件

javascript - 在 ACE 编辑器中更改行高?

javascript - 将 html 放入 iframe(使用 javascript)

node.js - 如何将 JSON 表单数据转换为 mongoose 模式?

javascript - node.js 进程.memoryUsage() ENOENT

javascript - 如何从异步调用返回响应?