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

时间:2013-11-03 20:59:25

标签: 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"}

1 个答案:

答案 0 :(得分:0)

错误处理错误导致脚本出错。

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

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