AngularJS + Socket.IO - 如何更新模型?
Posted
技术标签:
【中文标题】AngularJS + Socket.IO - 如何更新模型?【英文标题】:AngularJS + Socket.IO - how to update model? 【发布时间】:2013-09-01 11:29:11 【问题描述】:所以我有了这个用 AngularJS 制作的基本 CRUD Todo 应用程序。然后我想我想用一些 Socket.IO 来增加它的趣味性,使它成为一个实时网络应用程序。但是,我在让它正常工作时遇到了一些问题。
设置: 约曼(鲍尔+咕噜) AngularJS 要求JS NodeJS + MongoDB Socket.IO
我的“咕噜服务器”在 localhost:9000 上运行,而我的 NodeJS/MongoDB/Socket.IO 服务器在 localhost:4711 上运行
目前使用 Socket.IO 的功能是创建和删除待办事项,但我似乎不知道如何更新我的待办事项。我认为这很容易。
这是代码。
Socket.js:
var io = require('socket.io');
exports.initialize = function(server)
io = io.listen(server);
io.sockets.on('connection', function(socket)
socket.on('message', function(message)
message = JSON.parse(message);
socket.get('deletedTodo', function(err, nickname)
socket.broadcast.send(JSON.stringify(message));
socket.send(JSON.stringify(message));
);
);
socket.on('delete_todo', function(data)
socket.set('deletedTodo', data.title, function()
socket.emit('todo_delete', data);
socket.broadcast.emit('todoDeleted', data);
);
);
socket.on('update_todo', function(data)
socket.broadcast.emit('todoUpdated', data);
)
);
这是我的客户端代码。
Services.js:
/*global define*/
define(['angular'], function(angular)
'use strict';
return angular.module('services', [])
.factory('Todo', function($resource)
//var baseUrl = 'http://designit-todo.eu01.aws.af.cm/api/todos/:id';
var baseUrl = 'http://localhost:port/api/todos/:id';
return $resource(baseUrl,
port: ':4711', id: '@_id',
'update': method:'PUT',
'delete': method:'DELETE', isArray: true
);
)
.factory('socket', function($rootScope)
var socket = io.connect('http://localhost:4711');
return
on: function(eventName, callback)
socket.on(eventName, function()
var args = arguments;
$rootScope.$apply(function()
callback.apply(socket, args);
)
);
,
emit: function(eventName, data, callback)
socket.emit(eventName, data, function()
var args = arguments;
$rootScope.$apply(function()
if (callback)
callback.apply(socket, args);
);
);
,
send: function(eventName, data, callback)
socket.send(eventName, data, function()
var args = arguments;
$rootScope.$apply(function()
if (callback)
callback.apply(socket, args);
);
);
);
);
Controllers.js:
/*global define*/
define(['angular', 'services/services'], function(angular)
'use strict';
return angular.module('controllers', ['services'])
.controller('Todos', ['$scope', '$resource', 'Todo', '$location', 'socket', function($scope, $resource, Todo, $location, socket)
// Grab all todos.
$scope.todos = Todo.query();
socket.on('message', function(data)
// Grab all todos when new added via socket.
$scope.todos = Todo.query();
$scope.todos.push(data);
);
// Complete/update todo.
$scope.todoCompleted = function(todo)
todo.$update();
socket.emit('update_todo', todo);
socket.on('todoUpdated', function(todo)
// Update on all connected clients.
console.log(todo);
);
$scope.removeTodo = function(todo)
var index = $scope.todos.indexOf(todo);
socket.emit("delete_todo", JSON.stringify(index));
$scope.todos.splice(index, 1);
todo.$remove();
socket.on('todoDeleted', function(index)
$scope.todos.splice(index, 1);
);
])
.controller('Single', ['$scope', '$resource', '$routeParams', 'Todo', '$timeout', '$location', function($scope, $resource, $routeParams, Todo, $timeout, $location)
// Grab just a single todo
$scope.todo = Todo.get( id: $routeParams.id );
// Throttle the update PUT request
var saveTimeout;
$scope.save = function()
$timeout.cancel(saveTimeout);
saveTimeout = $timeout(function()
// Save the todo and then update the scope
$scope.todo.$update(function(updated_todo)
$scope.todo = updated_todo;
);
, 1000);
;
])
.controller('Add', ['$scope', '$resource', 'Todo', '$location', 'socket', function($scope, $resource, Todo, $location, socket)
$scope.todo = new Todo();
$scope.save = function()
if ($scope.todo.title)
$scope.todo.$save(function(data)
console.log(data);
socket.send(JSON.stringify(data));
$location.path('/');
);
]);
);
所以我的问题在于这段代码:
// Complete/update todo.
$scope.todoCompleted = function(todo)
todo.$update();
socket.emit('update_todo', todo);
socket.on('todoUpdated', function(todo)
// Update on all connected clients.
console.log(todo);
);
当我使用 console.log(todo) 时,我得到了 todo,但我可以对其执行“todo.$update”。我也尝试过类似的方法:
socket.on('todoUpdated', function(todo)
var thisTodo = Todo.get(id: todo._id);
console.log(thisTodo);
);
但是一旦我尝试这样做Todo.$update() 我得到一个错误:
PUT http://localhost:4711/api/todos 404 (Not Found) :4711/api/todos:1
我做错了什么?如果我在代码中做错了什么,请纠正我。我对 AngularJS 和 Socket.IO 还是很陌生。
【问题讨论】:
问题不在于socket.io,这一切似乎都有效。问题在于您的 API。显然,您正在尝试使用id
1
更新待办事项,但服务器似乎找不到此待办事项。 Postman 是一个测试 API 的好工具:chrome.google.com/webstore/detail/postman-rest-client/…
嗯.. 我不认为我的 API 有问题?我已经尝试使用适用于 Chrome 的 Advanced Rest Client,GET、POST、PUT 和 DELETE 都可以在 localhost:4711/api/todos 上正常工作
检查 Angular 试图在你的开发工具中执行的确切 PUT 请求,并将其与您使用 Rest Client 执行的请求进行比较。那么 PUT 请求一定有问题。
我刚刚在 .todoCompleted 方法上尝试了这个:var thisTodo = Todo.get(id: todo._id); thisTodo.$update();
现在这两个客户端都出现了同样的错误。
您可以在此处查看错误:cl.ly/image/3u1b0a2m0G1c 和此处:cl.ly/image/432R3n2s062A
【参考方案1】:
我找到了另一个解决方案,但不确定它是否是正确的方法:
socket.on('todoUpdated', function(updated_todo)
for (var i in $scope.todos)
if ($scope.todos[i]._id == updated_todo._id)
$scope.todos[i] = updated_todo;
);
所以在 Todos 控制器中,我有 $scope.todos 来保存所有的 todos。然后我遍历所有这些,在 id 上找到匹配项并将找到的 todo 设置为新更新的 todo。
如果有更好的方法,请告诉我:)
【讨论】:
以上是关于AngularJS + Socket.IO - 如何更新模型?的主要内容,如果未能解决你的问题,请参考以下文章
改进这个 AngularJS 工厂以与 socket.io 一起使用
如何使用 Express、AngularJS、Socket.io 广播和获取通知?