fs.writefile只能在节点js的最后一个函数中执行

我的程序有三个function如下所示,

var userId = req.userId; var appId = req.body.appId; var main = 'temp/' + userId + '/templates/' + appId + '/css/main.css'; var color = req.body.color; var font = req.body.font; var fontSize = req.body.fontSize; replaceThemecolor(color); replaceFont(font); replaceFontSize(fontSize); function replaceThemecolor(color) { fs.readFile(main, 'utf-8', function (err, data) { var regex =/(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/; var result = data.replace(regex, "$1" + color + "$3"); console.log(color); fs.writeFile(main, result, 'utf-8', function (err) { if (err) return console.log(err); }); }); } function replaceFont(font) { fs.readFile(main, 'utf-8', function (err, data) { var regex =/(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/; var result = data.replace(regex, "$1" + font + "$3"); console.log(font); fs.writeFile(main, result, 'utf-8', function (err) { if (err) return console.log(err); }); console.log(result); }) } function replaceFontSize(fontSize) { fs.readFile(main, 'utf-8', function (err, data) { var regex =/(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/; var result1 = data.replace(regex, "$1" + fontSize + "em" + "$3"); console.log(fontSize); fs.writeFile(main, result1, 'utf-8', function (err) { if (err) return console.log(err); }); }); } 

在这里只有最后一个函数会一直执行,当我单独执行它们的时候它们工作的很好,但是当所有的函数一次执行时就会出现问题。 这是fs.writeFile函数的问题吗? 我想一起执行这三个函数,有没有办法做到这一点? 这里的所有function在分开执行的时候都能正常工作。

你的文件function是asynchronous的。 你不能同时运行它们,因为它们会冲突,会覆盖另一个的变化。 你必须运行一个,然后当它完成时,运行另一个。

或者,甚至更好,只读取一次文件,处理所有更改的数据,然后写入一次。


如果你要按顺序运行它们,那么你需要传递一个callback给你的每一个被调用的函数,这样你就可以知道什么时候开始下一个函数了。


但是,我认为更好的解决scheme是传递一系列replace指令,并在文件的一次读写中处理所有这些指令。 我将为此编写一个代码示例。

这里有一种方法可以在文件的一次读写中进行所有的更新,并使用promise来知道操作何时完成:

 function updateFile(filename, replacements) { return new Promise(function(resolve, reject) { fs.readFile(filename, 'utf-8', function(err, data) { if (err) { reject(err); } else { // now cycle through and do all the replacements for (var i = 0; i < replacements.length; i++) { data = data.replace(replacements[i].regex, replacements[i].replacer); } fs.writeFile(filename, data, 'utf-8', function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); } updateFile(main, [{regex: /(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + color + "$3"}, {regex: /(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + font + "$3"}, {regex: /(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/, replacer: "$1" + fontSize + "em$3"}]).then(function() { // update done successfully }, function(err) { // error }); 

有了更多的工作,你也许可以只从正则expression式中抽象出关键字,所以你只需要传递关键字,但是我会把它留给另外一个时间。


这里是一个简化的版本:

 function updateFile(filename, replacements) { return new Promise(function(resolve, reject) { fs.readFile(filename, 'utf-8', function(err, data) { var regex, replaceStr; if (err) { reject(err); } else { // now cycle through and do all the replacements for (var i = 0; i < replacements.length; i++) { regex = new Regex("(\\" + replacements[i].rule + "\\s*{[^}]*" + replacements[i].target + "\\s*:\\s*)([^\\n;}]+)([\\s*;}])"); replaceStr = "$1" + replacements[i].replacer + "$3"; data = data.replace(regex, replaceStr); } fs.writeFile(filename, data, 'utf-8', function(err) { if (err) { reject(err); } else { resolve(); } }); } }); }); } updateFile(main, [ {rule: ".made-easy-themeColor", target: "color", replacer: color}, {rule: ".made-easy-themeFont", target: "font-family", replacer: font}, {rule: ".made-easy-themeFontSize", target: "font-size", replacer: fontSize + "em"} ], function() { // update done successfully }, function(err) { // error }); 

而且,如果你不想知道什么时候全部完成或者能够返回错误(我不build议这样做,但代码更简单),则不必使用这个承诺。

 function updateFile(filename, replacements) { fs.readFile(filename, 'utf-8', function(err, data) { var regex, replaceStr; if (err) { return; } // now cycle through and do all the replacements for (var i = 0; i < replacements.length; i++) { regex = new Regex("(\\" + replacements[i].rule + "\\s*{[^}]*" + replacements[i].target + "\\s*:\\s*)([^\\n;}]+)([\\s*;}])"); replaceStr = "$1" + replacements[i].replacer + "$3"; data = data.replace(regex, replaceStr); } fs.writeFile(filename, data, 'utf-8'); }); } updateFile(main, [ {rule: ".made-easy-themeColor", target: "color", replacer: color}, {rule: ".made-easy-themeFont", target: "font-family", replacer: font}, {rule: ".made-easy-themeFontSize", target: "font-size", replacer: fontSize + "em"} ], function() { // update done successfully }, function(err) { // error }); 

注意添加更多replace是多么容易。 您只需在传递给updateFile()的数组中添加一行即可。

Node.js本质上是asynchronous的。 因此,您正在快速连续执行三个读取操作,然后尝试写入已locking文件的文件,或者至less在读取文件时不包含写入更改。 我会使用更像async的系列或瀑布方法来解决这个问题。

 var async = require("async"); var userId = req.userId; var appId = req.body.appId; var main = 'temp/' + userId + '/templates/' + appId + '/css/main.css'; var color = req.body.color; var font = req.body.font; var fontSize = req.body.fontSize; async.series({ replaceThemecolor: function(callback) { fs.readFile(main, 'utf-8', function(err, data) { var regex = /(\.made-easy-themeColor\s*{[^}]*color\s*:\s*)([^\n;}]+)([\s*;}])/; var result = data.replace(regex, "$1" + color + "$3"); console.log(color); fs.writeFile(main, result, 'utf-8', function(err) { callback(err); }); }); }, replaceFont: function(callback) { fs.readFile(main, 'utf-8', function(err, data) { var regex = /(\.made-easy-themeFont\s*{[^}]*font-family\s*:\s*)([^\n;}]+)([\s*;}])/; var result = data.replace(regex, "$1" + font + "$3"); console.log(font); fs.writeFile(main, result, 'utf-8', function(err) { callback(err); }); }) }, replaceFontSize: function(callback) { fs.readFile(main, 'utf-8', function(err, data) { var regex = /(\.made-easy-themeFontSize\s*{[^}]*font-size\s*:\s*)([^\n;}]+)([\s*;}])/; var result1 = data.replace(regex, "$1" + fontSize + "em" + "$3"); console.log(fontSize); fs.writeFile(main, result1, 'utf-8', function(err) { callback(err); }); }); } }, function(err, results) { // results is empty, but now the operation is done. });