javascript - Node.js 触发回调两次,为什么?

标签 javascript node.js

在下面的代码中,为什么 createFile 回调会触发两次?仅当服务器(如下)同时处理两个或多个请求时才会发生这种情况,而不是仅发出一个请求时才会发生。输出在帖子底部。发出请求的客户端不是浏览器,而是另一个 Node.js 脚本,该脚本迭代目录并将带有文件的 http post 请求发送到服务器。请求是这样创建的:

fs.createReadStream(fileName).pipe(httprequest(options, function(error, response, body) { }));
function myRequest(request, response) {
  function writeFile(filePath, request, callback) {
    newFilePath = "/home/pi/upload"+filePath; //filePath looks like this: /home/blah/file.txt, the code below creates this structure under another directory, so newFilePath becomes /home/pi/upload/home/blah/file.txt
    tempFileName = path.basename(filePath)+".temp";
    console.log("Processing "+filePath+"->"+newFilePath+" with tempname " +tempFileName);
    var createFile = request.pipe(fs.createWriteStream(tempFileName));
    createFile.on("finish", function(error) { //Why does it fire the callback twice?
      if(error) {
        throw error;
      } else {
        moveFile(tempFileName, newFilePath, function(error) {
          if(error) {
            throw error;
          } else {
            console.log("OK");
          }
        });
      }
    });
  }

  function moveFile(tempFileName, newFilePath, callback) {
    dirPath = path.dirname(newFilePath);
    fs.stat(dirPath, function(error, stats) { //check if dir exists
      if(error == null) {
        console.log(dirPath+" already exists");
        fs.stat(tempFileName, function(error, stats) { //check if file exists
          if(error == null) {
            console.log("OK, writing "+newFilePath);
            fs.rename(tempFileName, newFilePath, function(error) {
              if(error) { //Error on the second run, because the file has been moved in the first run, shouldn't happen?
                throw error;
              } else {
                var myCB = JSON.stringify({fMove: "OK"});
                callback(myCB);
              }
            });
          } else {
            console.log("File exists");
          }
        });
      }
    });
  }
  writeFile(fileName, request, function() {
    //Do some stuff
  });
  request.on("end", function() {
    //Do other stuff
  }
});

http.createServer(myRequest).listen(8888);

我的脚本的输出

Processing /home/pi/app/temp/client.js->/home/pi/upload/home/pi/app/temp/client.js with tempname client.js.temp
/home/pi/upload/home/pi/app/temp already exists
/home/pi/upload/home/pi/app/temp already exists
OK, Writing /home/pi/upload/home/pi/app/temp/client.js
OK, Writing /home/pi/upload/home/pi/app/temp/client.js

/home/pi/app/server.js:67
            throw error;
                  ^
{"fMove":"OK"}

最佳答案

不正确的错误处理导致脚本出现错误。

在moveFile函数中这部分是错误的:

fs.rename(tempFileName, newFilePath, function(error) {
              if(error) {
                throw error;
              } else {
                var myCB = JSON.stringify({fMove: "OK"}); 
                callback(myCB); // <-- Malformatted callback! Should be callback(null, myCB);
              }

这使得 writeFile 的这一部分触发错误并由于某种原因运行两次:

moveFile(tempFileName, newFilePath, function(error) { //Should be moveFile(tempFileName, newFilePath, function(error, status) {
          if(error) {
            throw error;
          } else {
            console.log("OK");
          }
        });

当我修复代码以使其正确处理错误时,它会按预期工作!

关于javascript - Node.js 触发回调两次,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19758051/

相关文章:

javascript - 缩小浏览器窗口时的水平滚动条

node.js - 删除除用户写入的文本之外的所有内容

angularjs - MEAN 和地理空间查询 - 查找与给定名称的另一个相交的 LineStrings

javascript - 服务器生成内容之上的 AngularJS

node.js - 我正在尝试调用 aws nodejs SDKdescribeStacks(云形成)来获取堆栈的详细信息。我收到错误。下面给出代码和响应

node.js - Mongoose promise 与 bluebird 和 typescript

node.js - 在 Heroku 上遇到主机名/IP 与证书的替代名称不匹配

javascript - 将点击事件函数应用于多个元素,包括 if/else

javascript - Ajax调用不将数据存储在数组中

javascript - webkit-transform 覆盖 Chrome 13 中的 z-index 排序