我相信应该是
connection.client.populateSomeInformation = function () { .. )
(不是connection.server)
http://www.asp.net/signalr/overview/hubs-api/hubs-api-guide-javascript-client#callclient
(对你现在在 github 上的代码的观察)
var isLoaded = false;
// ... some code that doesn't change isLoaded ...
if (isLoaded == false) {
scrollIntervalId = window.setInterval(function () {
signalRLoaded();
}, 30);
}
我认为isLoaded
在这一点上永远是错误的。不确定你打算完成什么。
var connection = $.connection.hub.start();
我认为您不应该在定义任何客户端功能之前打开连接。我没有看到这里定义了任何客户端函数,所以也许你正在其他地方这样做?除了服务器是否尝试调用尚未定义的客户端函数之外,我不知道这是否真的很重要......
function SignalRReady(callback) {
if (isLoaded) {
callback(connection);
} else {
readyCalls = callback;
}
return SignalRReady;
}
SignalRReady.version = "1.0.0";
SignalRReady.load = function(name, request, onLoad, config) {
if (config.isBuild) {
onLoad();
} else {
SignalRReady(onLoad);
}
};
return SignalRReady;
我对这段代码感到困惑,可能是因为我看不到它是如何被使用的。这是对单例的尝试吗?我看到 SignalRReady 是为模块返回的“类”。您并没有真正返回一个对象,而是返回了一个构造函数,这意味着您正在其他地方实例化它,例如
define(['SignalRReady'], function(sigR)
{
var srr = new sigR();
});
但是随后您load
定义了调用构造函数的函数并使这看起来很奇怪。你怎么用这个?
无论如何,我认为您可能会遇到某种竞争条件,即客户端功能在服务器尝试调用它时可能并不总是可用。
(附加评论/代码 2013-09-06)
您的连接对象实际上是一个 jQuery 承诺(http://api.jquery.com/category/deferred-object/)。
如果您不熟悉 Promise,请将它们一般地视为稍后执行的回调队列。在这种情况下,当连接时,所有的回调都将被执行(按照它们被添加的顺序)。如果在连接后添加回调,它将立即执行。这就是您的代码现在的工作方式。在建立连接并立即执行后,您将回调添加到 .done 队列。
如果您坚持自己创建连接对象,则不需要使用 stateChanged 事件。您只需将回调添加到 .done 队列:
define(function()
{
function signalRReady(callback)
{
if (window.connection == undefined) {
window.connection = $.connection.hub.start();
}
window.connection.done(callback);
}
signalRReady.version = "1.0.0";
return signalRReady;
});
但是,我认为自己发起连接并不是一个好主意。由于您的模块不是 SignalR 的完整包装器,因此人们只会使用您的模块来执行 SignalR 的工作,因此不能保证(并且不能期望)其他代码不会启动连接。特别是如果有人将您的模块添加到现有代码库中。
您的模块只是添加一个新事件,因此请保持简单。接受回调并在适当的时候自己执行它:
define(function()
{
function signalRReady(callback)
{
$.connection.hub.stateChanged(function (state)
{
if(state.newState === $.signalR.connectionState.connected)
{
callback();
}
});
}
signalRReady.version = "1.0.0";
return signalRReady;
});
如今,承诺非常流行。您可能希望实现一个基于承诺的模块,例如:
define(function()
{
var deferred = $.Deferred();
$.connection.hub.stateChanged(function (state)
{
if(state.newState === $.signalR.connectionState.connected)
{
// executes all callbacks attached by the "ready" function below
deferred.resolve();
}
});
return {
ready: function(callback)
{
deferred.done(callback);
},
version: "1.0.0"
};
});
如果在建立连接后附加回调,它们会立即执行。
另外,请注意这个示例模块的 init 函数返回一个对象而不是一个函数。由于 RequireJS 会将相同的实例传递给任何需要它的模块,因此状态得以维护——我们可以使用局部变量而不是全局变量。