SignalR的RequireJS模块

时间:2013-06-06 20:19:24

标签: requirejs signalr

我没有将代码复制并粘贴到此处,而是将其上传到github。 RequireJS模块确实依赖于jquery.signalr,并且tern依赖于jquery,但也依赖于/ signalr / hubs中保存的javascript。有一些与Require.Config配置的配置。

基本上发生的事情是在您第一次加载页面时,连接到信号器内的集线器并执行“服务器端”代码并执行所需的操作。当您刷新页面时,它不会。调用所有客户端代码,例如:

var myViewModel = new MyViewMode();
myViewModel.init();

并在您的init方法中

var connection = $.connection.myHub;
this.init = function() {
  connection.server.myMethod();
}

然后会转到

public MyHub : Hub 
{
    public void MyMethod()
    {
        Client.Request.populateSomeInformation() // I think it's request but I'm doing this from memory!
    }
}

然后致电

connection.client.populateSomeInformation = function () { .. )

但不称之为:(

看起来就像已建立连接一样(使用旧的console.log()来查看它输出的内容)并确实调试项目它在集线器中执行代码但是没有响应回到了javascript。

互联网上这么好的人,我哪里错了?在尝试再次启动之前,是否需要检查$.connection.hub.start();的状态?

啤酒的时间:)

1 个答案:

答案 0 :(得分:1)

我认为应该是

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/)。

如果您不熟悉承诺,请将它们一般地视为稍后要执行的回调队列。在这种情况下,连接时,将执行所有回调(按照添加的顺序)。如果在连接后添加回调,它将立即执行。这就是您的代码现在的工作方式。在建立连接后将回调添加到.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会将相同的实例传递给任何需要它的模块,因此维护状态 - 我们可以使用局部变量而不是全局变量。