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

时间:2015-08-28 04:10:50

标签: regex angularjs node.js fs

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

    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函数的问题吗?我想一起执行这三个功能,有没有办法做到这一点?这些功能在单独执行时效果很好。

2 个答案:

答案 0 :(得分:1)

您的文件功能是异步的。您无法同时运行它们,因为它们会发生冲突,并且会覆盖另一个的更改。你必须运行一个,然后当它完成时,运行另一个。

或者,更好的是,只读取文件一次,处理包含所有更改的数据,然后再写一次。

如果您要按顺序运行它们,那么您需要将回调传递给完成后调用的每个函数,以便知道何时启动下一个函数。

但是,我认为更好的解决方案是传递一组替换指令,并在一次读取和写入文件时处理所有这些指令。我将为此编写一个代码示例。

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

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

通过更多的工作,你可能只抽出正则表达式中的关键字,所以你只需要传递关键字,但我会把它留到另一个时间。

这是一个简化版本:

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

而且,如果你不想知道它什么时候完成或者能够返回错误(我不会这样做),你根本不必使用这个承诺。推荐,但代码更简单。)

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

请注意添加更多替换是多么容易。您只需在传递updateFile()的数组中再添加一行。

答案 1 :(得分:1)

Node.js本质上是异步的。因此,您要快速连续执行三次读取操作,然后尝试写入已经锁定文件的文件,或者至少在读取文件时,不包含写入更改。我会使用更像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.
});