我在node.js项目中使用'replace-in-file'模块。我编写了下面的节点模块和app.js文件到(1)从网页获取表单数据,(2)从模板创建新文件,(3)迭代数据对象中的每个键/值对,(3) 4)对于每个键值对,在新文件中搜索与键匹配的字符串,并用键的相应值替换,并(5)将新文件的名称返回给客户端。
当应用运行时,会创建一个新文件,但新文件中反映的唯一搜索和替换似乎是最后搜索并替换.forEach()循环运行。< / p>
为什么我的搜索和替换都没有显示在新文档中?
这是我写的名为make-docs.js的模块:
var fs = require('fs');
var replace = require('replace-in-file');
var path = require('path');
// function to build agreement file
exports.formBuild = function(data){
var fileName = data.docType + Date.now() + '.html';
var filePath = __dirname + '/documents/' + fileName;
// make a new agreement
fs.createReadStream(data.docType + '.html').pipe(fs.createWriteStream(filePath));
Object.keys(data).forEach(function(key){
var options = {
//Single file
files: filePath,
//Replacement to make (string or regex)
replace: key,
with: data[key].toUpperCase(),
//Specify if empty/invalid file paths are allowed, defaults to false.
//If set to true these paths will fail silently and no error will be thrown.
allowEmptyPaths: false,
};
replace(options)
.then(changedFiles => {
console.log('Modified files:', changedFiles.join(', '));
console.log(options);
})
.catch(error => {
console.error('Error occurred:', error);
});
})
}
var express = require("express");
var fs = require("fs");
var bodyParser = require("body-parser");
var makeDocs = require("./make-docs.js");
var path = require('path');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/documents', express.static(path.join(__dirname, 'documents')));
app.post("/docs", function(req, res) {
console.log(req.body);
res.send(makeDocs.formBuild(req.body));
});
app.listen(8080,function(){
console.log("Node server listening on port 8080");
});
答案 0 :(得分:1)
这是因为你同时启动了几个替换,而它们在后台发生异步。所以会发生的是每个替换操作都会读取文件内容,这些文件内容在开始时没有改变,然后进行替换,但只有一个替换文件保存到文件中(最后一个)。
要绕过设置中的这个特定问题,请使用replace.sync
API进行同步替换:
try {
let changedFiles = replace.sync(options);
console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
console.error('Error occurred:', error);
}
但是请注意,这将阻止脚本的执行(并减慢您的请求),同时进行所有替换。对于小文件和少量替换,这应该不是问题,但对于较大的文件和更多的替换它可能是。所以建议使用后台进程来进行这些替换,但这超出了这个答案的范围。
replace-in-file
软件包尚不支持您进行多个不同替换的用例,但我已添加此功能,因为它似乎很有用。
所以现在你可以同时进行多次替换(同步或异步):
const replaceInFile = require('replace-in-file');
const replace = [/replace/g, /also/g];
const with = ['something', 'else'];
const files = [...];
replaceInFile({files, replace, with})
.then(changedFiles => { ... })
.catch(error => { ... });
您可以使用键/值对填充对象中的replace
和with
数组。如果要使用相同的替换替换多个值,可以使用replace
的字符串。
希望这有帮助。
为了完整起见,以下是逐个异步处理替换的方法:
const Promise = require('bluebird');
const replace = [/replace/g, /also/g];
const with = ['something', 'else'];
const file = '...';
Promise
.map(replace, (replacement, i) => {
return replaceInFile({
files: file,
replace: replacement,
with: with[i],
});
})
.then(() => {
//read file now which will contain all replaced contents
});
请注意,这是一个简化示例,并假设replace
和with
数组的大小相同。有关如何使用串行/并行等承诺的更多详细信息,请查看Bluebird库。