【问题标题】:socket.io - socket.on wait for promisesocket.io - socket.on 等待承诺
【发布时间】:2013-11-05 16:45:15
【问题描述】:

我有一个按钮可以与服务器进行一些通信,以检查输入的值(通过输入框)是否已经存在。代码如下:

$("#button").click(function () {
    var exists = false;
    var name = $("#name").val();
    socket.emit("check", name);

    socket.on("checkReturn", function (data) {
        exists = data.result;
    });

    if (exists) {
        console.log("exists")
    } else {
        if (name.length > 0) {
            socket.emit("create", name);
        }
    }
});
});

问题在于checkReturn 调用是异步的,因此代码继续执行而不实际等待结果。如何确保 checkReturn 首先完成,然后才执行其余代码?

【问题讨论】:

    标签: javascript jquery node.js socket.io promise


    【解决方案1】:

    除了其他答案,您还可以使用确认,在客户端和服务器之间传递回调。然后就可以直接使用emit函数的回调了:

    $("#button").click(function() {
      var exists = false; 
      var name = $("#name").val(); 
    
      socket.emit('check', name, function (data) { 
        exists = data.result;
        if (exists) console.log("exists");
        else (if (name.length > 0) socket.emit("create", name));
      });
    });
    

    在服务器端它看起来像这样:

    io.sockets.on('connection', function (socket) {
      socket.on('ferret', function(name, fn) {
        // find if "name" exists
        fn({ exists: false });
      });
    });
    

    【讨论】:

    • 这个解决方案对我来说效果更好。你能用几行解释一下 fn() 回调是如何工作的吗?我无法理解它。
    • fn() 是一个回调函数。在 JavaScript 中,您可以将一个函数传递给另一个函数,然后再调用它。在这种情况下,Socket.IO 实现了“确认”,您将一个函数传递给服务器,然后服务器调用该函数。
    • 谢谢,非常感谢。
    • 您的示例有点奇怪...名称不匹配。请参阅此处的文档示例:socket.io/docs/#sending-and-getting-data-%28acknowledgements%29
    【解决方案2】:

    @hexacyanide aswer 的替代方法可以这样做:

    $("#button").click(async function() {
      var exists = false; 
      var name = $("#name").val(); 
    
      exists = await new Promise(resolve => socket.emit('check', name, data => resolve(data.result)))
    
      if (exists) console.log("exists");
      else (if (name.length > 0) socket.emit("create", name));
    });
    

    套接字发射被包裹在一个承诺中,因此它可以等待回调,并避免嵌套在多个花括号内。

    不是那么优雅,但如果将代码封装在一个单独的函数中,可以使您的代码更易于阅读:

    function check(name){
      return new Promise(resolve => socket.emit('check', name, data => resolve(data.result)))
    }
    

    并像这样使用:

    $("#button").click(async function() {
      var exists = false; 
      var name = $("#name").val(); 
    
      exists = await check(name)
    
      if (exists) console.log("exists");
      else (if (name.length > 0) socket.emit("create", name));
    });
    

    【讨论】:

      【解决方案3】:
      $("#button").click(function () 
      { var exists = false; 
      var name = $("#name").val(); 
      socket.emit("check", name);
      
      socket.on("checkReturn", function (data) { 
      exists = data.result;
      if (exists) { console.log("exists") } else { if (name.length > 0) { socket.emit("create", name); } } });    
      });
      

      【讨论】:

      • 所以我应该把所有东西都包装在 socket.on 调用中?
      【解决方案4】:

      您可以使用 socket.io.wait 从 socket.io 获取同步响应:

      https://www.npmjs.com/package/socket.io.wait

      $("#button").click(async function ()
      {
          var exists = false;
          var name = $("#name").val();
      
          let exists = await socket.emitWait("check", name);
      
      
          if (exists == true)
          {
              console.log("exists");
          } 
          else
          {
              if (name.length > 0)
              {
                  socket.emit("create", name);
              }
          }
      });
      

      【讨论】:

        猜你喜欢
        • 2013-09-16
        • 2019-04-29
        • 2020-10-31
        • 2019-12-10
        • 1970-01-01
        • 2021-08-29
        • 2020-07-19
        • 2018-01-17
        • 2018-08-27
        相关资源
        最近更新 更多