FullCalendar RefetchEvents非常慢

时间:2016-05-25 16:50:08

标签: meteor fullcalendar

我在autorun Block中调用calendar.refetchEvents();以确保调度程序的反应性(我正在使用资源视图),当使用大数据集进行测试时,尽管我确保只下标2周的部分值事件发生得非常缓慢。

我的事件不是基于Json,我正在使用meteor,我循环遍历日历的Events函数内的事件。 我缺少一些好的全日历练习吗?

calendar = $('#calendar').fullCalendar({

        now: new Date(),
        editable: true, // enable draggable events
        droppable: true, // this allows things to be dropped onto the calendar
        aspectRatio: 1.8,
        disableDragging: true,
        displayEventTime: false,
        selectable:true,
        allDaySlot:true,
        slotDuration:'24:00',
        lazyFetching:true,
        scrollTime: '00:00', // undo default 6am scrollTime
        header: {
            left: 'today prev,next',
            center: 'title',
            right: 'timelineThreeDays'
        },
        defaultView: 'timelineThreeDays',
        views: {
            timelineThreeDays: {
                type: 'timeline',
                duration: { days: 14 }
            }
        },
        eventAfterAllRender: function(){
            Session.set("loading",false);
        },
        resourceLabelText: 'Employees',
        eventRender: function (event, element) {
            var originalClass = element[0].className;

            if (event.id && event.id.indexOf("temp")>-1){
                element[0].className = originalClass + ' dragEvent';
            }
            else if (event.id && event.id.indexOf("oloc")>-1){
                element[0].className = originalClass + ' oloc';
            }
            else{
                element[0].className = originalClass + ' hasmenu';
            }
            $(element[0]).attr('shift-id', event._id);

            element.find('.fc-title').html((event.title?event.title+"<br/>":"")+(event.locationName?event.locationName+"<br/>":"")+moment(event.start).format("HH:mm")+ " "+moment(event.end).format("HH:mm"));
            element.bind('mousedown', function (e) {
                if (e.which == 3) {
                    Session.set("selectedShift",event._id);
                }
            });

        },eventAfterRender: function(event, element, view) {

        },
        resourceRender: function(resourceObj, labelTds, bodyTds) {
            var originalClass = labelTds[0].className;
            var uid=resourceObj.id;
            var resource = Meteor.users.findOne({_id:uid});
            if(resource){
                var img = Images.findOne({_id: resource.picture});
                var imgUrl = img ? img.url() : "/images/default-avatar.png";
                var styleString = "<img class='img-profil small' src='"+imgUrl+"'>" + resource.profile.firstname + " " + resource.profile.lastname+" <small style='font-size:0.6em;color:#D24D57;'>"+resource.profile.registeredTelephony+"</small>";
                labelTds.find('.fc-cell-text').html("");
                labelTds.find('.fc-cell-text').prepend(styleString);
                labelTds[0].className = originalClass + ' hasResourceMenu';
            }else{
                var imgUrl = "/images/default-avatar.png";
                var styleString = "<img class='img-profil small' src='"+imgUrl+"'>" + "Unassigned" + " " +" <small style='font-size:0.6em;color:#D24D57;'>"+"</small>";
                labelTds.find('.fc-cell-text').html("");
                labelTds.find('.fc-cell-text').prepend(styleString);
            }

        },
        resources: function(callback) {
            var users = [];
            var data = Meteor.users.find({
                $or:[
                    {"profile.showInScheduler":{$exists:false}},
                    {"profile.showInScheduler":true}
                ],
                assignedTo:{$in:[Session.get("locationId")]},
                'locations._id':Session.get("locationId"),
                "profile.companyId":Session.get("companyId")
            });

            var arr = data.map(function(c) {
                var employeeType = c.userSettings.employeeType;
                var type = EmployeeType.findOne({_id:employeeType});
                var img = Images.findOne({_id: c.picture});
                var imgUrl = img ? img.url() : "/images/default-avatar.png";
                c.name = c.name || "";

                var totalHoursAllLocation = 0;
                var totalHoursCurrentLocation = 0;
                return {
                    id: c._id,
                    title: "t"
                };
            });
            arr.push({id:"temp"+Session.get("companyId")+Session.get("locationId"),title:"<div class='img-profil small' style='background: url(/images/default-avatar.png);'></div> UnAssigned"});
            callback(arr);
        },
        events: function(start, end, timezone, callback) {
        },
        drop: function(date, jsEvent, ui, resourceId) {
            // retrieve the dropped element's stored Event Object
            var locationId=Session.get("locationId");
            var originalEventObject = $(this).data('eventObject');
            var copiedEventObject = $.extend({}, originalEventObject);

            // assign it the date that was reported
            copiedEventObject.start = date;
            //copiedEventObject.allDay = allDay;
            shift = ShiftTypes.findOne({_id:copiedEventObject.id});
            if(shift){

                startDate = moment(date);
                hour = shift.dayDuration.Start.split(":");
                startDate.hours(hour[0]).minutes(hour[1]);
                endDate = moment(date);
                hour = shift.dayDuration.End.split(":");
                endDate.hours(hour[0]).minutes(hour[1]);
                if(moment(startDate).isAfter(endDate)){
                    endDate=endDate.add("1","days");
                }
                var data = {
                    shiftId:shift._id,
                    name:shift.name,
                    uid:resourceId,
                    locationId:Session.get("locationId"),
                    companyId:Session.get("companyId"),
                    day:date,start:startDate.utc().toDate(),
                    end:endDate.utc().toDate(),
                    type:"active"
                };

                if (SchedulesBeforeInsert(data,"dropActive")){
                    Schedules.insert(data,function (err,result) {});
                }

            }

        },
        eventResize: function( event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, view ) {
            endDate = moment.utc(new Date(event.start));
            schedule = Schedules.findOne({_id:event.id});
            var delta = dayDelta._days;
            for(i=1;i<delta+1;i++){
                Schedules.insert({start:moment.utc(event.start).add(i,"days").toDate(),end:moment.utc(schedule.end).add(i,"days").toDate(),uid:schedule.uid,locationId:Session.get("locationId"),companyId:schedule.companyId,name:schedule.name,shiftId:schedule.shiftId,attendanceCode:schedule.attendanceCode,type:schedule.type});
            }
        },
        dayClick: function(date, jsEvent, view,res,res2) {
            Session.set("selectedDay",moment(date).toDate());
            Session.set("selectedRessource",res.id);

        },
        eventClick: function ( event, jsEvent, view )  {

            toastr.success(moment(event.start).format('HH:mm') +" TO "+moment(event.endDate).format('HH:mm'))

        },
        eventReceive: function(event) { // called when a proper external event is dropped
            console.log('eventReceive', event);
        }
    }).data().fullCalendar;

/********************* reactive calendar *****************/

this.autorun(function() {
    console.log("autoRun")
    Meteor.subscribe("schedules",Session.get("companyId"),moment($('#calendar').fullCalendar('getDate')).startOf('week').toDate(),moment($('#calendar').fullCalendar('getDate')).add(4,"weeks").endOf('week').toDate());
    var events = [];
    var usersInLocation = Meteor.users.find({$or:[{"profile.showInScheduler":{$exists:false}},{"profile.showInScheduler":true}],assignedTo:{$in:[Session.get("locationId")]},'locations._id':Session.get("locationId"),"profile.companyId":Session.get("companyId")}).fetch();
    var userIds = _.pluck(usersInLocation,"_id");
    userIds.push("temp"+Session.get("companyId")+Session.get("locationId"));
    var data;
    if(Session.get("displayAllLocations")===true){
        reqEvents = Schedules.find({uid:{$in:userIds},companyId:Session.get("companyId"),type:{$in:["active","activeAttendance"]},start:{$gte:moment(Session.get("currentDate")).startOf('week').toDate()},end:{$lte:moment(Session.get("currentDate")).add(1,"week").endOf('week').toDate()}});
    }else{
        reqEvents = Schedules.find({uid:{$in:userIds},locationId:Session.get("locationId"),companyId:Session.get("companyId"),type:{$in:["active","activeAttendance"]},start:{$gte:moment(Session.get("currentDate")).startOf('week').toDate()},end:{$lte:moment(Session.get("currentDate")).add(1,"week").endOf('week').toDate()}});

    }
    reqEvents.forEach(function(evt){
        var event = null;
        color="";
        if(evt.attendanceCode){
            attendance =AttendanceCodes.findOne({_id:evt.attendanceCode});
            color=attendance.color;
        }
        attendance = null;
        color="";
        id="";
        locationName="";
        if(evt.attendanceCode){
            attendance =AttendanceCodes.findOne({_id:evt.attendanceCode})
            if(attendance){
                color=attendance.color;
            }

        }
        else if(evt.employeeAttendanceCode){
            attendance =AttendanceCodesPortal.findOne({_id:evt.employeeAttendanceCode})
            if(attendance){
                color=attendance.color;
            }
        }
        id=evt._id;
        if(evt.locationId!==Session.get("locationId")){
            color="#EEEEEE";
            id="oloc";
            location =Locations.findOne({_id:evt.locationId});
            if(location){
                locationName=location.name;
            }

        }
        if(evt.name != null){
            event = {id:id,title:evt.name,start:evt.start,end:evt.end,color:color,resourceId:evt.uid,locationName:locationName};
        }else{
            event = {id:id,title:" ",start:evt.start,end:evt.end,color:color,resourceId:evt.uid,locationName:locationName};
        }
        events.push(event);
    });


    allUsersCursor =Meteor.users.find({
        $or:[
            {"profile.showInScheduler":{$exists:false}},
            {"profile.showInScheduler":true}
        ],
        assignedTo:{$in:[Session.get("locationId")]},
        'locations._id':Session.get("locationId"),
        "profile.companyId":Session.get("companyId")
    }).fetch();


    if(calendar){
        calendar.removeEvents();
        calendar.addEventSource(events);
        calendar.refetchResources();
        //SetUp the actions context menu
        setUpContextMenu();

        // Initialize the external events
        $('#external-events div.external-event').each(function() {

            var eventObject = {
                title: $.trim($(this).text()), // use the element's text as the event title
                id:$(this).attr("id")
            };

            // store the Event Object in the DOM element so we can get to it later
            $(this).data('eventObject', eventObject);
            // make the event draggable using jQuery UI
            $(this).draggable({
                helper: 'clone',
                revert: 'invalid',
                appendTo: 'body'// original position after the drag
            });
        });
    }
});

1 个答案:

答案 0 :(得分:3)

我可以看到你应该优化的许多非流星图案:

  1. 您的this.autorun会在Schedules集合中的任何更改以及各种用户对象更改时重新运行(不仅仅是登录用户,还包括其他用户)。您的自动运行每次都从头开始重建客户端数据,包括大量连接。您可以使用local collection来缓存已连接的数据,然后仅在基础持久文档更改时添加/更改这些文档。这可以使用observeChanges模式完成。或者您可以对数据模型进行非规范化以避免所有这些连接。
  2. 您通过使用jQuery而不是使用Meteor事件处理程序将事件附加到多个选择器来修改DOM。这也发生在您的自动运行中,这意味着您将重复将相同的事件附加到相同的DOM对象。
  3. 您使用了许多Session个变量并重复使用它们。这些可能很慢,因为它们使用浏览器本地存储。你应该只将.get()这样的数据放入局部变量一次,然后从那时开始引用局部变量。
  4. 确保您只在您的代码实际上在客户端上引用的Schedules出版物中包含字段。其余的都是开销。