Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript UI路由器的角度服务异步单例_Javascript_Angularjs_Asynchronous_Angular Ui Router - Fatal编程技术网

Javascript UI路由器的角度服务异步单例

Javascript UI路由器的角度服务异步单例,javascript,angularjs,asynchronous,angular-ui-router,Javascript,Angularjs,Asynchronous,Angular Ui Router,我正在使用一个角度的应用程序。我通过一个$http异步调用获取数据,该调用用于创建各种连接对象。我的目标是有一些方法来创建这个对象,并使它作为一个单例可用。虽然发生这种情况的可能性很小,但我希望避免在异步分配服务中的socket属性时出现计时问题。当路由器中的不同状态想要获取或创建另一个连接对象时,它将通过单例来获取或创建另一个连接对象,以便可以使用相同的连接,而不是创建另一个连接 下面是我正在尝试使用的一些代码的框架。我不确定是否可以用状态的resolve做些什么 关于如何做到这一点,有什么想

我正在使用一个角度的应用程序。我通过一个
$http
异步调用获取数据,该调用用于创建各种连接对象。我的目标是有一些方法来创建这个对象,并使它作为一个单例可用。虽然发生这种情况的可能性很小,但我希望避免在异步分配服务中的
socket
属性时出现计时问题。当路由器中的不同状态想要获取或创建另一个连接对象时,它将通过单例来获取或创建另一个连接对象,以便可以使用相同的连接,而不是创建另一个连接

下面是我正在尝试使用的一些代码的框架。我不确定是否可以用状态的
resolve
做些什么

关于如何做到这一点,有什么想法或建议吗

var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', function($http) {
    var socket;

    // Somehow call and store result of $http in a singleton
    // Would the $http.get get put in some kind of function? If so, how should it get called 
    // and returned so that a user of the service can get the 'socket' object synchronously?
        $http.get("something/that/returns/data")
            .success(function (result) {
                this.socket= createConnection(result.data);
            })
            .error(function (err) {
                //handle error
            })

    var getSocket= function() {
        if (!this.socket) {
            return createNewSocket();
        } else {
            return this.socket;
        }
    }
}])

myapp.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("home");

    $stateProvider
        .state('home', {
            url: "/home",
            templateUrl: "home.html",
            resolve: {
                socket: // ??? Can something be done here ???
            },
            controller: function(socket) {
                // I can haz socket?
            }
        })
        .state('nextState', {
            url: "/next",
            templateUrl: "next.html",
            resolve: {
                socket: // Should be the same socket object as from the home state
            },
            controller: function(socket) {
                // I can haz same socket?
            }
        })
})

更新

在试图更好地解释这个问题的过程中,我已经多次更改了原始代码。人们留下的评论纠正了我所犯的明确错误。我已经将上面的代码恢复到原来的状态,并在下面添加了新代码。我仍然面临的问题是,在进入控制器之前,ui路由器状态上的
resolve
没有解决。因此,在对应该解析的
socket
对象调用
emit()
时,出现错误“无法读取未定义的属性'emit'。我还希望
socket
对象在状态之间是相同的对象。如果有任何其他建议或意见可以引导我朝着正确的方向前进,我将不胜感激

var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', function($http) {
    var socket;

    // Somehow call and store result of $http in a singleton
    // Would the $http.get get put in some kind of function? If so, how should it get called 
    // and returned so that a user of the service can get the 'socket' object synchronously?
    $http.get("something/that/returns/data")
        .then(function (result) {
            socket = createConnection(result.data);
        }, function (err) {
            // handle error
        });

    var getSocket = function() {
        if (!socket) {
            // handle error
        } else {
            return socket;
        }
    }
}])

myapp.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("home");

    $stateProvider
        .state('home', {
            url: "/home",
            templateUrl: "home.html",
            resolve: {
                socket: function(connectionService) {
                    return connectionService.getSocket();
                }
            },
            controller: function(socket) {
                socket.emit("some msg");
            }
        })
        .state('nextState', {
            url: "/next",
            templateUrl: "next.html",
            resolve: {
                socket: function(connectionService) {
                    return connectionService.getSocket();
                }
            },
            controller: function(socket) {
                socket.emit("some other msg");
            }
        })
})

更新2

这是一个可行的解决方案,但这并不像人们所接受的正确答案那样优雅

我考虑创建自己的承诺,并将其作为ui路由器需要解决的问题返回。根据我所有的调试和堆栈跟踪,在状态之间只创建了一个连接,进入控制器的操作被延迟,直到连接被解析。因此,我相信这是一个有效的解决方案。我还有一个版本的代码,在解析承诺之前处理连接上的
onConnect
事件,但为了简洁起见,我省略了它

var myapp = angular.module('me', ['ui.router'])
.service('connectionService', ['$http', '$q', function($http, $q) {
    var socket;

    this.getSocket = function() {
        if (!socket) {
            var deferred = $q.defer();

            $http.get("something/that/returns/data")
                .then(function (result) {
                    socket = createConnection(result.data);
                    deferred.resolve(socket);
                }, function (err) {
                    // handle error
                    deferred.reject(socket);
                });

            return deferred.promise;
        } else {
            return socket;
        }
    }
}])

myapp.config(function($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise("home");

    $stateProvider
        .state('home', {
            url: "/home",
            templateUrl: "home.html",
            resolve: {
                socket: function(connectionService) {
                    return connectionService.getSocket();
                }
            },
            controller: function(socket) {
                socket.emit("some msg");
            }
        })
        .state('nextState', {
            url: "/next",
            templateUrl: "next.html",
            resolve: {
                socket: function(connectionService) {
                    return connectionService.getSocket();
                }
            },
            controller: function(socket) {
                socket.emit("some other msg");
            }
        })
})

据我所知,每次套接字实例无效时,您都希望根据
$http.get
中的数据初始化套接字,但在应用程序加载时异步初始化

.service('connectionService', ['$http', '$q', function($http, $q) {
    //For caching the socket
    var socket;

    //Do the first get
    tryGetData();

    //tryGetData executes $http.get and returns a promise that when fulfilled -
    //returns the new socket instance.
    function tryGetData(){
     return $http.get("something/that/returns/data")
        .then(function (result) {
            return socket = createConnection(result.data);
        }, function (err) {
            // handle error
        });
    }

    //Whenever getSocket gets called, it first checks if the socket is instantiated. if not -
    //assumes the $http.get failed and tries again to instantiate the socket calling
    //$http.get again in the process.
    //this function returns a promise for controllers to rely on.
    this.getSocket = function(){
     if(socket) return $q.resolve(socket);
     return tryGetData();
    }
}]);

其余的代码看起来不错。

在angular中,服务是单例的,因此这确实是您想要的。但是,您的服务构建方式存在一些问题;具体来说,您在回调中使用
。此
将无法按预期工作,因为
。此
指的是回调,而不是父服务。此外,您应该考虑切换到<代码>。然后,<代码> >而不是被禁止的<代码>。成功< /代码>。删除不赞成的<代码>。成功< /代码>并切换到<代码>。然后< /代码>约定。您仍然使用<代码>。这是不起作用的主要部分。在angular services和factory中是单例的。如果您是Javascript新手,那么您将需要花一些时间阅读
这个
的工作原理,因为它是常见的bug源。这很接近,但tryGetData()并没有返回ui路由器的resolve可以处理的承诺。我有一个解决方案,我创建一个$q延迟对象并返回该延迟对象的承诺。我将发布该解决方案,但我想感谢您的帮助。是的,
$http
确实会返回一个承诺。但是按照这里编写的方式,
tryGetData()
不会返回该承诺,因为已经调用了
.then()
。不知道如何用合适的术语来解释它。此外,我还需要一种方法来处理从
$http.get
返回的数据,然后再返回promise结果。因此,我需要抓住
$http
承诺,并重新播放另一个。至少这是我的观察结果。我可能完全错了……你错了。检查这个:而且值得注意的是,既然承诺是单子,这就是为什么你可以像这样执行链接。太棒了。我不知道我之前尝试这个时是否忘记重新加载代码或其他东西。它现在肯定能工作了,当然也省去了我添加的所有额外内容。我确实学到了很多。谢谢你的帮助!