【问题标题】:Errors when using socket.io in AngularJs on user updates在用户更新中使用 AngularJs 中的 socket.io 时出错
【发布时间】:2015-08-30 01:32:53
【问题描述】:

您好,我正在尝试在用户更改首选语言时自动更新文章列表。

我试图做到这一点的方法是,每当用户在数据库中更改时更新IO socket

但是我的努力似乎并不成功,我不知道为什么。

由于我是socket.io的新手,我想我会在这里向编码大神寻求帮助。

愿软件与你同在^^

PS:该项目是一个Angular fullstack 项目,脚手架是Yeoman


代码时间!


client/components/articlebar/articlebar.controller.js

'use strict';

angular.module('unityAcademyApp')
.controller('ArticlebarCtrl', function ($scope, $location, Auth, socket) {
  $scope.articles = {};

  function populateArticles(){ 
       ...
        Some functionality where $scope.articles are set
        ...
    };

    socket.syncUpdates('user', $scope.articles, function() {
        console.log('hit');
        populateArticles();
    });
});


client/components/socket/socket.service.js

/* global io */
'use strict';

angular.module('unityAcademyApp')
  .factory('socket', function(socketFactory) {

    // socket.io now auto-configures its connection when we ommit a connection url
    var ioSocket = io('', {
      // Send auth token on connection, you will need to DI the Auth service above
      // 'query': 'token=' + Auth.getToken()
      path: '/socket.io-client'
    });

    var socket = socketFactory({
      ioSocket: ioSocket
    });

    return {
      socket: socket,

      /**
       * Register listeners to sync an array with updates on a model
       *
       * Takes the array we want to sync, the model name that socket updates are sent from,
       * and an optional callback function after new items are updated.
       *
       * @param {String} modelName
       * @param {Array} array
       * @param {Function} cb
       */
      syncUpdates: function (modelName, array, cb) {
        cb = cb || angular.noop;

        /**
         * Syncs item creation/updates on 'model:save'
         */
        socket.on(modelName + ':save', function (item) {
          var oldItem = _.find(array, {_id: item._id});
          var index = array.indexOf(oldItem);   // this is line 39
          var event = 'created';

          // replace oldItem if it exists
          // otherwise just add item to the collection
          if (oldItem) {
            array.splice(index, 1, item);
            event = 'updated';
          } else {
            array.push(item);
          }

          cb(event, item, array);
        });

        /**
         * Syncs removed items on 'model:remove'
         */
        socket.on(modelName + ':remove', function (item) {
          var event = 'deleted';
          _.remove(array, {_id: item._id});
          cb(event, item, array);
        });
      },

      /**
       * Removes listeners for a models updates on the socket
       *
       * @param modelName
       */
      unsyncUpdates: function (modelName) {
        socket.removeAllListeners(modelName + ':save');
        socket.removeAllListeners(modelName + ':remove');
      }
    };
  });


server/config/socketio.js

/**
 * Socket.io configuration
 */

'use strict';

var config = require('./environment');

// When the user disconnects.. perform this
function onDisconnect(socket) {}

// When the user connects.. perform this
function onConnect(socket) {
    // When the client emits 'info', this listens and executes
    socket.on('info', function (data) {
        console.info('[%s] %s', socket.address, JSON.stringify(data, null, 2));
    });

    // Insert sockets below
    require('../api/translation/translation.socket').register(socket);
    require('../api/comment/comment.socket').register(socket);
    require('../api/article/article.socket').register(socket);
    require('../api/language/language.socket').register(socket);
    require('../api/thing/thing.socket').register(socket);
    require('../api/user/user.socket').register(socket);
}

module.exports = function (socketio) {
    // socket.io (v1.x.x) is powered by debug.
    // In order to see all the debug output, set DEBUG (in server/config/local.env.js) to including the desired scope.
    //
    // ex: DEBUG: "http*,socket.io:socket"

    // We can authenticate socket.io users and access their token through socket.handshake.decoded_token
    //
    // 1. You will need to send the token in `client/components/socket/socket.service.js`
    //
    // 2. Require authentication here:
    // socketio.use(require('socketio-jwt').authorize({
    //   secret: config.secrets.session,
    //   handshake: true
    // }));

    socketio.on('connection', function (socket) {
        socket.address = socket.handshake.address !== null ?
            socket.handshake.address.address + ':' + socket.handshake.address.port :
            process.env.DOMAIN;

        socket.connectedAt = new Date();

        // Call onDisconnect.
        socket.on('disconnect', function () {
            onDisconnect(socket);
            console.info('[%s] DISCONNECTED', socket.address);
        });

        // Call onConnect.
        onConnect(socket);
        console.info('[%s] CONNECTED', socket.address);
    });
};


server/api/user/user.socket.js

/** * 当模型改变时向客户端广播更新 */

'use strict';

var User = require('./user.model');

exports.register = function(socket) {
  User.schema.post('save', function (doc) {
    onSave(socket, doc);
  });
  User.schema.post('remove', function (doc) {
    onRemove(socket, doc);
  });
}

function onSave(socket, doc, cb) {
  socket.emit('user:save', doc);
}

function onRemove(socket, doc, cb) {
  socket.emit('user:remove', doc);
}

目前遇到的错误

到目前为止,运行代码时出现以下错误

TypeError: array.indexOf is not a function
    at Socket.<anonymous> (socket.service.js:39)
    at socket.js:24
    at angular.js:17782
    at completeOutstandingRequest (angular.js:5490)
    at angular.js:5762
        (anonymous function)        @ angular.js:12416
        $get                        @ angular.js:9203
        (anonymous function)        @ angular.js:17785
        completeOutstandingRequest  @ angular.js:5490
        (anonymous function)        @ angular.js:5762

【问题讨论】:

    标签: javascript angularjs node.js sockets


    【解决方案1】:

    我不确定您为什么会收到该错误,但我想我知道您的数据为什么没有更新。

    您必须将回调函数包装在 $timeout 函数中才能触发您的更改。例如,您可以这样做:

    $timeout(function(){
        cb(event, item, array);
    }, 0);
    

    记得在你的套接字工厂中包含$timeout 指令。

    【讨论】:

    • 我之前一直在使用这个脚手架工具,我没有$timeout 触发更改的函数,socket.io 通常会自己处理。当我更新article 等项目时触发有效,但更新user 时无效。您能否详细说明为什么您认为本案有必要这样做?
    • 哦,忘记脚手架部分。它发生在我身上一次,因为我使用的是原始 socket.io 库,所以它没有触发 $scope 更改。我已经用完了这样的东西:gist.github.com/muZk/829c7e845f3098bc5c76关于错误,检查你的“数组”设置函数,它可能是一个对象,而不是在执行的某个点的数组。
    • 啊我明白了,在那种情况下我明白你为什么要使用它^^ 关于数组,对象olditemundefined 出于某种原因,我正在运行代码以看看为什么。然而没有运气
    【解决方案2】:

    什么是'取消划线'是什么意思?我不确定'undescore',但我想这是'this'的别名。我认为你应该初始化 var _ = this。

    我只是猜测。

    【讨论】:

      【解决方案3】:

      我发现了问题。

      由于在文章列表中查找用户而导致的错误,由于没有任何匹配项而返回undefined。因此解决方案是更改client/ components/ articlebar/ articlebar.controller.js中的代码

      来自

      socket.syncUpdates('user', $scope.articles, function() {
          console.log('hit');
          populateArticles();
      });
      

      socket.syncUpdates('user', $scope.users, function() {
          console.log('hit');
          populateArticles();
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-04
        • 1970-01-01
        • 1970-01-01
        • 2015-09-20
        • 1970-01-01
        • 2016-10-04
        • 2018-02-25
        • 1970-01-01
        相关资源
        最近更新 更多