如何从socket.io高效率

时间:2015-11-25 03:56:56

标签: node.js socket.io reactjs flux immutable.js

我的前端页面由React + Flux制作,它将script data发送到后端nodejs服务器。

script dataArray,其中包含linux shell参数(超过100000)。何时收到后端,它将执行linux shell命令。

只是一个例子:

cat ~/testfile1
cat ~/testfile2
          .
          .
          .
(100000 times ...etc)

当后端完成其中一个linux shell命令后,我可以将readed内容保存到result data。因此,socket.io会将result data发送到前端。

我想实时从我的网页上获取result data,所以我在下面的项目中做了一些事情。

我的React component代码:

import React from 'react';

import AppActions from '../../../actions/app-actions';
import SocketStore from '../../../stores/socket-store';
import ResultStore from '../../../stores/result-store';

function getSocket () {
    return SocketStore.getSocket();
}

function getResult () {
    return ResultStore.getResultItem();
}

class ListResultItem extends React.Component {
    constructor () {
        super();
    }
    render () {
        return <li>
                {this.props.result.get('name')} {this.props.result.get('txt')}
            </li>;
    }
}

class ShowResult extends React.Component {
    constructor () {
        super();
        this.state = {
            socket: getSocket(),
            result: getResult()
        };
    }
    componentWillMount () {
        ResultStore.addChangeListener(this._onChange.bind(this));
    }
    _onChange () {
        this.setState({
            result: getResult()
        });
    }
    render () {
        return <div>
                <ol>
                    {this.state.result.map(function(item, index) {
                        return <ListResultItem key={index} result={item} />;
                    })}
                </ol>
            </div>;
    }
    componentDidMount () {
        this.state.socket.on('result', function (data) {
            AppActions.addResult(data);
        });
    }
}

我的Flux store (ResultStore)代码:

import AppConstants from '../constants/app-constants.js';
import { dispatch, register } from '../dispatchers/app-dispatcher.js';
import { EventEmitter } from 'events';
import Immutable from 'immutable';

const CHANGE_EVENT = 'changeResult';

let _resultItem = Immutable.List();

const _addResult = (result) => {
    let immObj = Immutable.fromJS(result);

    _resultItem = _resultItem.push(immObj);
}

const _clearResult = () => {
    _resultItem = _resultItem.clear();
}

const ResultStore = Object.assign(EventEmitter.prototype, {
    emitChange (){
        this.emit( CHANGE_EVENT );
    },
    addChangeListener (callback) {
        this.on(CHANGE_EVENT, callback);
    },
    removeChangeListener (callback) {
        this.removeListener(CHANGE_EVENT, callback);
    },
    getResultItem () {
        return _resultItem;
    },
    dispatcherIndex: register(function (action) {
        switch (action.actionType) {
            case AppConstants.ADD_RESULT:
                _addResult(action.result);
            break;
            case AppConstants.CLEAR_RESULT:
                _clearResult();
            break;
        }

        ResultStore.emitChange();
    })
});

然而,在渲染超过1000个数据后,页面将变得非常慢。如何提升渲染性能?我需要持续执行linux脚本超过3天。有解决方案吗感谢〜

1 个答案:

答案 0 :(得分:1)

是否需要在屏幕上呈现所有数据?如果没有,那么有几种方法可以减少可见数据的数量。

过滤/搜索

您可以提供一个补充列表的搜索/过滤器组件,并创建一个谓词函数,该函数可用于确定是否应该呈现每个项目。

<PredicateList>
  <Search />
  <Filter />
  {this.state.result
     .filter(predicate)
     .map(function(item, index) {
       return <ListResultItem key={index} result={item} />;
     })
  }
</PredicateList>

延迟加载

仅在要求时加载项目。您可以通过跟踪它是否在屏幕上,或鼠标是否在屏幕上来确定是否需要该项目。

var Lazy = React.createClass({
  getInitialState: function() {
    return { loaded: false };
  },
  load: function() {
    this.setState({ loaded: true });
  },
  render: function() {
    var loaded = this.state.loaded,
        component = this.props.children,
        lazyContainer = <div onMouseEnter={this.load} />;

    return loaded ?
      component
      lazyContainer;
  }
});

然后简单地将数据项包装在这些Lazy包装器中,以便在请求它们时进行渲染。

<Lazy>
  <ListResultItem key={index} result={item} />
</Lazy>

这确保只能看到用户所需的数据。您还可以改进加载触发器以适应更复杂的场景,例如当组件在屏幕上停留超过2秒时。

分页

最后,最后和最经过考验的方法是分页。选择可以一次显示的多个数据项的限制,然后允许用户以块的形式浏览数据集。

var Paginate = React.createClass({
  getDefaultProps: function() {
    return { items: [], perPage: 100 }; 
  },
  getInitialState: function() {
    return { page: 0 };
  },
  next: function() {
    this.setState({ page: this.state.page + 1});
  },
  prev: function() {
    this.setState({ page: this.state.page - 1});
  },
  render: function() {
    var perPage = this.props.perPage,
        currentPage = this.state.page,
        itemCount = this.props.items.length;

    var start = currentPage * perPage,
        end = Math.min(itemCount, start + perPage);

    var selectedItems = this.props.items.slice(start, end);

    return (
      <div className='pagination'>
        {selectedItems.map(function(item, index) {
          <ListResultItem key={index} result={item} />
        })}
        <a onClick={this.prev}>Previous {{this.state.perPage}} items</a>
        <a onClick={this.next}>Next {{this.state.perPage}} items</a>
      </div>
    );
  }
});

这些只是用于以有效方式管理大量数据呈现的实现的非常粗略的示例,但希望它们对您实现自己的解决方案有足够的意义。