在node-js中写入IO

时间:2016-09-30 16:07:51

标签: node.js concurrency io file-writing

我有一个node.js(语法实际上是Typescript)应用程序:

  • 在某个HTTP请求处理程序中异步地在文件中写入每日计数和
  • 一个cron作业(使用node-cron模块完成的节点应用程序内部),在午夜重置该文件

非阻塞事件循环循环对我来说不是很清楚(如果我做对了,我会在引擎盖下it's not single thread)并且我担心cron模块正在重置文件的情况#39;写信给他。

我要担心吗?就像我的宣传fs.writeFile写作时设置的全局标志一样?有没有更优雅的方式来处理它?<​​/ p>

如果这是一个愚蠢的问题,谢谢,对不起。

这是我的代码的骨架:

import * as fs from 'fs';
import * as path from 'path';
import { CronJob } from 'cron';
import { pfs } from './promisifiedFs';

const daily_file = '/path_to_my_file'


new CronJob('0 0 * * * *', function() {
  fs.writeFileSync(daily_file, 0, {'flag': 'w'});
}, null, true);


// somewhere called inside an HTTP GET handler
async function doBill(data) {

  const something = //....

  const currentCountRaw = await pfs.readfilePromisified(daily_file, 'utf-8');
  const currentCount = parseFloat(currentCountRaw) || 0;
  await pfs.writeFilePromisified(daily_file, currentCount + something, {'flag': 'w'});

}

2 个答案:

答案 0 :(得分:2)

在Node.js 中,您的代码在单个线程中运行。它是单线程的,除非您使用执行异步I / O的本机模块,如果您使用{{3模块。

当您在脚本中使用writeFileSync时,主线程将阻塞,直到您完成此操作并且不会并行执行任何其他操作。

编辑:如评论中所述,可能会发生这样的情况:cron作业在读取和写入之间运行。还有一种情况不太可能发生但可能:异步写入已经在运行并且cronjob正在运行。所以我回复了我所说的内容,因为它错了,建议创建一个互斥锁,如变量或锁定文件。

答案 1 :(得分:0)

我建议使用类似async queue的内容(如果您只运行节点应用程序的一个实例)或lockfile(如果您打算群集或使用多个进程)。

这里有一些代码(我相信)会复制我上面列出的问题,通过写更大的值来增加多次写入冲突的可能性。

我的电脑似乎做的是fs.writeFileSync并且......什么都不做?我可能会弄错,但这是我正在使用的代码。我选择co代替async/await以避免需要转换。

const fs = require('fs');
const co = require('co');
const crypto = require('crypto');

function wait(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

function now() {
  return new Date().toISOString();
}

function log(...args) {
  return console.log(now(), ...args);
}

const file = './output.txt';

log('generating bytes...');
const bytes = crypto.randomBytes(100000000);
log('done generating bytes');

function writeAsync() {
  return new Promise((resolve, reject) => {
    return fs.writeFile(file, bytes.toString('base64'), { 'flag': 'w' }, err => {
      if (err) {
        return reject(err);
      }
      return resolve();
    });
  });
}

function writeSync() {
  fs.writeFileSync(file, 'FINDMEFINDMEFINDME', { 'flag': 'w' });
}

function run() {
  return co(function*() {
    log('before write async');
    const promise = writeAsync().then(() => log('after write async'));
    const ms = 1;
    log(`waiting for ${ms} ms`);
    yield wait(ms);
    log('done waiting');
    log('before write sync');
    writeSync();
    log('after write sync');
    yield promise;
  });
}

run().catch(err => console.error(err));

示例输出:

2016-10-03T22:52:05.032Z generating bytes...
2016-10-03T22:52:06.846Z done generating bytes
2016-10-03T22:52:06.848Z before write async
2016-10-03T22:52:06.999Z waiting for 1 ms
2016-10-03T22:52:07.001Z done waiting
2016-10-03T22:52:07.001Z before write sync
2016-10-03T22:52:07.012Z after write sync
2016-10-03T22:52:08.623Z after write async

行为:

似乎文件输出包含writeAsync()的结果,而writeSync()对输出没有影响。老实说,我有点想要抛出一个错误。甚至可能writeSync()'FINDMEFINDMEFINDME'放在其他代码的中间,但我无法在输出文件中找到该字符串。