我正在尝试理解一篇文章here,现在一切都很清楚但是一个代码片段,在前一个代码块上提到,总共有1到17行,而且这个片段来自于行1至9:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function() {
var soc = id && io.to(id);
soc.emit.apply(soc, arguments);
}
});
});
我认为它在我的javascript知识中的一些缺点是根本原因。 我对这段代码片段的了解:
问题:
请说清楚。
答案 0 :(得分:1)
此代码存在一些问题,但一般的想法是在req
对象req.emitToUser()
上为每个传入请求定义一个方法,该方法将允许链中的某些其他路由处理程序使用发出给发出请求的用户的方法。这是一种普遍的愿望,希望将当前连接的socket.io连接连接到发出http请求的用户。
让我们看看这一行:
redis.get(req.user.email, function(err, id) {
在redis数据库中查找req.user.email,以获取与之前保存在该redis数据库中的该电子邮件关联的socket.io标识。
if (err) next(err);
如果在redis中找不到,请将此请求失败并显示错误。
req.emitToUser = function() {
为当前req
对象分配一个新方法,以便链中稍后的其他路径处理程序可以使用该方法。
var soc = id && io.to(id);
在socket.io中查找id值以获取该id的套接字。从技术上讲,io.to()
不会返回套接字,但会返回一个可以调用emit()
的对象,该对象将发送到该套接字。
soc.emit.apply(soc, arguments);
soc.emit.apply(soc, arguments);
的作用是:
soc.emit()
方法this
值设置为soc
对象。req.emitToUser(x, y, z)
的参数。这是一个更具体的例子:
function fn(a, b, c) {
console.log(a, b, c);
}
fn.apply(null, [1, 2, 3]);
使用fn.apply(null, [1, 2, 3]);
将与:
fn(1, 2, 3);
现在,当参数已知时,您可能永远不会以这种方式使用.apply()
。使用它的情况是你有一些传递给你的任意数组(你不知道它在里面是什么),你想要以完全相同的顺序将这些参数传递给其他一些函数因为他们是给你的。那是soc.emit.apply(soc, arguments);
正在做的事情。它采用arguments
对象(这是一个类似于数组的结构,表示传递给父函数req.emitToUser()
的参数,并在其上传递那些确切的参数sock.emit()
。如果你确切地知道会有多少个参数,那么你可以硬编码相同的代码:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function(msg, data) {
var soc = id && io.to(id);
soc.emit(msg, data);
}
});
});
但是,.apply()
创建了一个更通用的解决方案,无论传递给req.emitToUser()
的参数有多少都会有效,因为它只会将所有参数传递给soc.emit()
。
这行代码有点怀疑:
var soc = id && io.to(id);
它似乎试图防止之前没有从redis返回的正确id。但是,如果没有id,那么soc
将不是有效的对象,而是以下代码:
soc.emit.apply(soc, arguments);
会抛出。因此,id && io.to(id)
并未真正提供适当的保护。看起来这应该更可能是:
app.use(function(req,res,next) {
redis.get(req.user.email, function(err, id) {
if (err) next(err);
req.emitToUser = function() {
if (id) {
var soc = io.to(id);
soc.emit.apply(soc, arguments);
} else {
// not sure what you want here, perhaps return an error
// or throw a more meaningful exception
}
}
});
});