多次连续调用回调函数会导致回调地狱

Multiple sequential calls to function with callback results in callback hell

本文关键字:回调 地狱 函数 连续 调用      更新时间:2023-09-26

我有一个函数,用于通过TCP/IP套接字与服务器通信。每次它向服务器写入命令时,都必须等待响应。我已经编写了一个工作良好的函数,看起来像这样简化:

function sendCommand(command, callback)
{
    // send command and wait for server to respond...
    // if response was ok
    callback(response, null);
    // if response was bad
    callback("", error);
}

这样做的问题是,我想发送命令序列到服务器,根据答案是什么,我要么想继续执行下一个命令,要么处理错误,不发送任何进一步的命令。

目前我使用这个函数如下:

sendCommand("first command to server", function(response, error)
{
    if(error)
    {
        // handle error
    }
    else
    {
        sendCommand("second command to server", function(response, error)
        {
            //etc..
        }
    }
}

当执行许多顺序调用时,这会导致回调地狱。如果我收到错误,是否有任何方法可以使条件调用链中断?比如:

sendCommand("command1", function(){})
.sendCommand("command2", function(){})
.sendCommand("command3", function(){})
.sendCommand("command4", function(){});

例如,如果command2收到错误,则永远不会执行command3和command4调用

您可能想要查看Promises而不是使用callbacks:

function sendCommand(command) {
  return new Promise(function(resolve, reject) {
    if(Math.random() > 0.6) {
      reject("Command " + command + " failed.");
    } else {
      resolve("Command " + command + " succeeded");
    }
  });
}
sendCommand("command1")
.then(function(data) {
  console.log(data); //Data from command1
  return sendCommand("command2");
})
.then(function(data) {
  console.log(data); //Data from command2
  return sendCommand("command3");
})
.then(function(data) {
  console.log(data); //Data from command3
  return sendCommand("command4");
})
.then(function(data) {
  console.log(data); //Data from command4
})
.catch(function(error) {
  console.log(error); //Error from any command
});

小提琴

更新1

根据失败的示例处理不同的错误:

function sendCommand(command) {
  return new Promise(function(resolve, reject) {
    if(Math.random() > 0.6) {
      reject({ command: command, msg: "Command " + command + " failed."});
    } else {
      resolve("Command " + command + " succeeded");
    }
  });
}
sendCommand("command1")
.then(function(data) {
  console.log(data); //Data from command1
  return sendCommand("command2");
})
.then(function(data) {
  console.log(data); //Data from command2
  return sendCommand("command3");
})
.then(function(data) {
  console.log(data); //Data from command3
  return sendCommand("command4");
})
.then(function(data) {
  console.log(data); //Data from command4
})
.catch(function(error) {
  switch(error.command) {
    case "command1":
      //Handle command1 error
      break;
    case "command2":
      //Handle command1 error
      break;
    case "command3":
      //Handle command1 error
      break;
    case "command4":
      //Handle command1 error
      break;
  }
  console.log(error.msg); //Error message from any command
});

小提琴