socket.io emit callback调用探秘

socket.io

https://socket.io/

https://socket.io/docs/

What Socket.IO is

Socket.IO is a library that enables real-time, bidirectional and event-based communication between the browser and the server. It consists of:

  • a Node.js server: Source | API
  • a Javascript client library for the browser (which can be also run from Node.js): Source | API

emit callback 用法

https://stackoverflow.com/questions/20337832/is-socket-io-emit-callback-appropriate

Recently I have been messing around with socket.io and found this interesting thing, that I can have emit function callback like this.

I start emitting on client side like this:

client.emit(‘eventToEmit‘, dataToEmit, function(error, message){
    console.log(error);
    console.log(message);
});

Then I can fire a callback from server-side like this:

client.on(‘eventToEmit‘, function(data, callback){
    console.log(data);
    callback(‘error‘, ‘message‘);
});

Everything works fine with no errors, but I am interested if doing something like this is appropriate since I have not seen anything similar in the documentation or any example so far.

见老外的疑惑,也是本篇的主题, 为什么服务器端能够直接调用客户端设置的回调函数。

跨进程可以调用函数,真是稀奇。 类似RPC。

官方文档的解释

https://socket.io/docs/#Sending-and-getting-data-acknowledgements

Sending and getting data (acknowledgements)

Sometimes, you might want to get a callback when the client confirmed the message reception.

To do this, simply pass a function as the last parameter of .send or .emit. What’s more, when you use .emit, the acknowledgement is done by you, which means you can also pass data along:

Server (app.js)

var io = require(‘socket.io‘)(80);

io.on(‘connection‘, function (socket) {  socket.on(‘ferret‘, function (name, word, fn) {    fn(name + ‘ says ‘ + word);  });});

Client (index.html)

<script>  var socket = io(); // TIP: io() with no args does auto-discovery  socket.on(‘connect‘, function () { // TIP: you can avoid listening on `connect` and listen on events directly too!    socket.emit(‘ferret‘, ‘tobi‘, ‘woot‘, function (data) { // args are sent in order to acknowledgement function      console.log(data); // data will be ‘tobi says woot‘    });  });</script>

代码跟踪

https://github.com/socketio/socket.io-client

以客户端源码为研究对象。

在socket.js文件中,存在emit实现:

如下代码中, 17-20行代码中, 会将callback函数存储到本地的acks数组中, 并将基数记为 packet.id,

然后packet作为数据整体,传送的服务器端。

 1 Socket.prototype.emit = function (ev) {
 2   if (events.hasOwnProperty(ev)) {
 3     emit.apply(this, arguments);
 4     return this;
 5   }
 6
 7   var args = toArray(arguments);
 8   var packet = {
 9     type: (this.flags.binary !== undefined ? this.flags.binary : hasBin(args)) ? parser.BINARY_EVENT : parser.EVENT,
10     data: args
11   };
12
13   packet.options = {};
14   packet.options.compress = !this.flags || false !== this.flags.compress;
15
16   // event ack callback
17   if (‘function‘ === typeof args[args.length - 1]) {
18     debug(‘emitting packet with ack id %d‘, this.ids);
19     this.acks[this.ids] = args.pop();
20     packet.id = this.ids++;
21   }
22
23   if (this.connected) {
24     this.packet(packet);
25   } else {
26     this.sendBuffer.push(packet);
27   }
28
29   this.flags = {};
30
31   return this;
32 };

服务器端处理完数据后, 调用callback接口后,服务器端调用的接口为包装接口, 包装了数据为packet, 并将id打在packet上, 表示此packet为emit时候的packet对应。

服务器端数据到来后, 根据packet.id定位到 callback函数, 并将packet.data作为参数传递到callback中。

/**
 * Called upon a server acknowlegement.
 *
 * @param {Object} packet
 * @api private
 */

Socket.prototype.onack = function (packet) {
  var ack = this.acks[packet.id];
  if (‘function‘ === typeof ack) {
    debug(‘calling ack %s with %j‘, packet.id, packet.data);
    ack.apply(this, packet.data);
    delete this.acks[packet.id];
  } else {
    debug(‘bad ack %s‘, packet.id);
  }
};

致此实现上彻底明了了。

原文地址:https://www.cnblogs.com/lightsong/p/10226940.html

时间: 2024-11-09 10:43:34

socket.io emit callback调用探秘的相关文章

使用 Socket.IO 开发聊天室

前言 Socket.IO 是一个用来实现实时双向通信的框架,其本质是基于 WebSocket 技术. 我们首先来聊聊 WebSocket 技术,先设想这么一个场景: · 用户小A,打开了某个网站的充值界面,该界面上有一个付款的二维码. · 当小A 用某宝的 APP 扫码付款之后,网页要自动跳转到付款成功的界面.最简单的方法就是网页每隔一段时间就请求一次服务器--"怎么样?那货付款没有?","怎么样?还没付吗?","怎么样?这次总该付了吧". ·

关于Socket.IO的知识点记录

最近因为项目的需要,开始学习nodejs,本着js的那点儿功底,nodejs学习起来还是挺快能上手的.随着深入学习,知道了express框架并那它写了一个小功能,作为一个php程序员哈,在express框架路由.模板渲染那里看到了Yii2的影子,所以便更加的亲切了.再接着便接触到了websocket,而今天谈论的socket.io 便是websocket的一个类库,说道这里了,我们先去了解下websocket和socket.io: 一  websocket WebSocket是html5新增加的

socket.io的emit使用清单

function onConnect(socket){ // 给本次连接的客户端发消息 socket.emit('hello', 'can you hear me?', 1, 2, 'abc'); // 给除了本次连接的其他所有连接者发消息 socket.broadcast.emit('broadcast', 'hello friends!'); // 给除了本次连接者之外的所有game房间的人发消息 socket.to('game').emit('nice game', "let's play

nodejs 基于socket.io实现聊天室

由于之后要做的网页视频直播项目要用到socket.io模块,所以特地花时间研究了下,参照网上的代码做了些改进,自己写了个聊天室代码.不得不承认后端事实推送能力有点厉害,这是以前我用php一直苦恼的事情.下面简单介绍下我的项目,顺带讲解下nodejs. 事实上,在看别人写的代码之前,我一直不知道nodejs是干嘛的,直到真正接触到才明白这也可以算作是服务端代码,丰富的第三方库使其功能极其强大.它可以像golang的beego一样直接通过命令行开启服务器,不过要用到express模块.加载模块的方式

Socket.IO API Socket

Socket Socket类继承自EventEmitter.覆写了emit方法,保留了EventEmitter的其他方法 socket.id 会话的唯一标识符,来自于底层的Client socket.rooms 标识此客户端所在房间的字符串哈希值,按房间名称编制索引 socket.client 对底层Client对象的引用. socket.conn 对底层Client传输连接的引用(engine.io Socket对象) socket.request 一个getter代理,它返回对request

学习 Socket.io

学习 Socket.io 官网:Socket.io 初次学习用于即时通信的技术,现将自己对 Socket.io 的理解记录在此,技术细节可以查看相关文档. 即时通信主要由服务端和客户端构成,服务端有一个,客户端有多个,Socket.io 实现了服务端与客户端的双向通信,因此可以进行即时通信. 简述 Socket.io 主要涉及到两个对象: Server 和 socket (有服务端 socket 和 客户端 socket ). 大致的工作流程: 服务端需要启动一个 Server 进行监听, 客户

Socket.IO初探

建立Server //server.jsvar io = require('socket.io')(80); var chat = io .of('/chat') //设定命名空间 .on('connection', function (socket) { socket.emit('a message', { //这个只会发送给自己的socket that: 'only' , '/chat': 'will get' }); chat.emit('a message', { //全局发送 ever

[Node.js] Level 6. Socket.io

6.2 Setting Up socket.io Server-Side So far we've created an Express server. Now we want to start building a real-time Q&A moderation service and we've decided to use socket.io. Using the http module, create an new http server and pass the expressapp

TCG开发日志(3)socket.io

为了让网页端和服务端能随时互相通讯,以前在HTTP下有多种写法,但是现在我们可以使用websocket,至少在Chrome上可以. 先安装socket.io npm install socket.io --save 在服务端,可以将socket.io和KOA结合起来: import Koa from 'koa';import IO from 'socket.io' let app = new Koa();let server = require('http').Server(app.callba