角度アプリにUI-Routerを使用しています。私は$http
非同期呼び出しを介して引っ張っているデータを持っています。これは、ソートの接続オブジェクトを作成するために使用されます。私の目標は、このオブジェクトを作成し、それをシングルトンとして利用できるようにすることです。それが起こる可能性はまれですが、サービス内のsocket
プロパティが非同期に割り当てられているタイミングの問題を避けることを検討しています。ルータ内の別の状態が別の接続オブジェクトを取得または作成したい場合は、シングルトンを介して行い、別の接続を作成する代わりに同じ接続を使用することができます。UI-Routerのための角度サービス非同期シングルトン
以下は、私が働くことを試みているいくつかのコードのスケルトンです。状態の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-router状態のresolve
がコントローラに入る前に解決していないということです。だから、解決しようとしているsocket
オブジェクトの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
が、これは正しい答えとして受け入れられてきたMuli Yulzariの答えのようにエレガントではありません。
私は自分の約束事を作り出し、それを解決するためにui-routerのためのものとして戻しました。私のデバッグとスタックのすべてのトレースに基づいて、状態間に1つの接続しか作成されず、接続が解決されるまでコントローラに入ることは延期されます。だから、これは実用的な解決策だと私は信じています。私は約束を解決する前に接続の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");
}
})
})
アングルでは、サービスはシングルトンなので、実際にはあなたが望むものになります。しかし、サービスの構築方法にはいくつかの問題があります。具体的には、 '.this'は親サービスではなくコールバックを参照するため、あなたの意図通りに' .this'をコールバック内で使用することはできません。また、廃止予定の '.success'の代わりに' .then'に切り替えることも考慮する必要があります。 – Claies
廃止予定の '.success'を削除し、'に切り替えました。それから約束する。 – BoJoe22
あなたはまだpromiseの中で '.this'を使っています。これは動作しない主な部分です。 – Claies