Javascript 尝试使用node.js模块&x27;替换为文件';,查找和替换文件中的多个字符串

Javascript 尝试使用node.js模块&x27;替换为文件';,查找和替换文件中的多个字符串,javascript,node.js,Javascript,Node.js,我正在为node.js项目使用“在文件中替换”模块。我在下面编写了节点模块和app.js文件,以(1)从网页获取表单数据,(2)从模板创建新文件,(3)迭代数据对象中的每个键/值对,(4)对于每个键-值对,在新文件中搜索与键匹配的字符串并替换为键的对应值,以及(5)将新文件的名称返回给客户端 当应用程序运行时,会创建一个新文件,但新文件中反映的唯一搜索和替换似乎是.forEach()循环运行的最后一次搜索和替换 为什么我的所有搜索和替换都没有显示在新文档中 以下是我编写的名为make-docs.

我正在为node.js项目使用“在文件中替换”模块。我在下面编写了节点模块和app.js文件,以(1)从网页获取表单数据,(2)从模板创建新文件,(3)迭代数据对象中的每个键/值对,(4)对于每个键-值对,在新文件中搜索与键匹配的字符串并替换为键的对应值,以及(5)将新文件的名称返回给客户端

当应用程序运行时,会创建一个新文件,但新文件中反映的唯一搜索和替换似乎是.forEach()循环运行的最后一次搜索和替换

为什么我的所有搜索和替换都没有显示在新文档中

以下是我编写的名为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=要求(“fs”);
var bodyParser=require(“主体解析器”);
var makeDocs=require(“./makeDocs.js”);
var path=require('path');
var-app=express();
use(bodyParser.urlencoded({extended:false}));
use(bodyParser.json());
app.use('/documents',express.static(path.join('documents'));
应用程序发布(“/docs”),功能(请求、回复){
控制台日志(请求主体);
res.send(makeDocs.formBuild(req.body));
});
app.listen(8080,函数(){
log(“在端口8080上侦听的节点服务器”);
});

这是因为您正在同步启动多个替换,而它们在后台异步进行。因此,每次替换操作都会读取文件内容,这些内容在开始时保持不变,然后进行替换,但只有一个替换保存到文件中(最后一个)

要在设置中避免此特定问题,请通过
replace.sync
API使用同步替换:

try {
  let changedFiles = replace.sync(options);
  console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
  console.error('Error occurred:', error);
}
但是请注意,在进行所有替换时,这将阻止脚本的执行(并降低请求的速度)。对于小文件和少量替换,这应该不是问题,但对于较大文件和更多替换,这可能是问题。因此,建议使用后台进程来进行这些替换,但这超出了本答案的范围

文件中的
replace
包还不支持您进行多个不同替换的用例,但我在中添加了此功能,因为它似乎很有用

因此,现在您可以一次进行多个替换(同步或异步):

您可以使用键/值对填充对象中的
replace
数组。如果要用相同的替换替换多个值,可以使用字符串替换
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库,了解有关如何使用串联/并联等承诺的更多详细信息。

Adam的诊断是正确的。但我希望他会告诉你如何串联异步任务。这是你可能需要学会做的事情,即使在这种情况下你不需要它。npm模块允许您以各种方式(并行、串行或介于两者之间)组合异步任务
async
bluebird
是两个这样的模块。您已经使用了promises语法,因此您可能会对
bluebird
更为熟悉。我同意David的观点,如果您想使用promises,我强烈推荐
bluebird
。我将更新我的答案,以包括一个关于如何使用promise界面的示例,并等待所有承诺完成。酷,我从发布这个问题中学到了很多!我现在正在读关于蓝鸟的书。我希望在改进代码的同时将其应用到我的应用程序中。谢谢你的意见!没问题!谢谢
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
    });