我有一个node.js(语法实际上是Typescript)应用程序:
非阻塞事件循环循环对我来说不是很清楚(如果我做对了,我会在引擎盖下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'});
}
答案 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'
放在其他代码的中间,但我无法在输出文件中找到该字符串。