2013-08-29 62 views
3

所以我有这个基于AngularJS的基础CRUD Todo应用程序。然后我想我想用一些Socket.IO来使它成为一个实时的Web应用程序。但是,我有一些问题让它正常工作。AngularJS + Socket.IO - 如何更新模型?

设置: 约曼(凉亭+咕噜) AngularJS RequireJS +的NodeJS MongoDB的 Socket.IO

我'咕噜服务器的运行在localhost:9000,而我的NodeJS /的MongoDB/Socket.IO服务器运行on localhost:4711

目前,Socket.IO的作用是创建和删除待办事项,但我似乎无法弄清楚如何更新我的待办事项。我认为会很容易。

这里是codez。

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); 
    }) 
    }); 
} 

这里是我的客户端codez。

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。$ update”。我也试过类似:

socket.on('todoUpdated', function(todo) { 
    var thisTodo = Todo.get({id: todo._id}); 
    console.log(thisTodo); 
    }); 

但只要我尝试做thisTodo $更新()我得到一个错误:

PUT http://localhost:4711/api/todos 404 (Not Found) :4711/api/todos:1 

我在做什么错?如果我在我的代码中做了任何错误,请纠正我。我对AngularJS和Socket.IO还是比较新的。

+0

的问题不在于socket.io,一切都似乎工作。问题在于你的API。显然,你正在尝试使用'id'' 1'更新待办事项,但服务器似乎无法找到这个待办事项。测试你的API的好工具是邮差:https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm/ – RoryKoehein

+0

嗯..我不认为这是错误的我的API?我已经尝试过使用高级Rest Rest Client for Chrome,并且GET,POST,PUT DELETE在http:// localhost:4711/api/todos上正常工作 – dgsunesen

+0

检查以了解Angular尝试执行的确切PUT请求在你的开发工具中,并将其与你正在使用Rest Client进行的请求进行比较。那么PUT请求肯定有问题。 – RoryKoehein

回答

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; 
    } 
    } 
}); 

所以在托多斯控制器我有$ scope.todos它包含所有待办事项。然后我遍历所有这些,在id上找到一个匹配,并将找到的待办事项设置为最新更新的待办事项。

如果有更好的方式来做到这一点,请你告诉我:)