2016-05-25 23 views
0

Ich rufe calendar.refetchEvents(); in einem Autorun-Block, um die Reaktivität des Schedulers zu gewährleisten (ich benutze Ressourcenansicht), wenn mit großen Datasets getestet, obwohl ich sicherstellen, nur einen Teil von 2 Wochen wert von Ereignissen ist es extrem langsam.FullCalendar RefetchEvents sehr langsam

Meine Ereignisse arent JSON basiert ich verwende Meteor und ich Schleife über die Ereignisse innerhalb der Ereignisse-Funktion des Kalenders. Gibt es einige gute Vollkalenderpraktiken, die ich vermisse?

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

Haben Sie Ihren Code profiliert? Netzwerk? Können Sie Code anzeigen? –

+0

Ich habe gerade etwas Code hinzugefügt, danke – Genjuro

Antwort

3

ich dort eine Reihe von Nicht-Meteoric Muster sehen, dass Sie bei der Optimierung sollten:

  1. Ihre this.autorun wird jederzeit etwas Änderungen in Ihrer Schedules Sammlung sowie für verschiedene Benutzerobjekt Änderungen erneut ausführen (nicht nur für die eingeloggten Benutzer, sondern auch für andere Benutzer). Ihr Autorun baut Ihre clientseitigen Daten jedes Mal neu auf, einschließlich zahlreicher Joins. Sie können local collection verwenden, um die verknüpften Daten zwischenzuspeichern und diese Dokumente nur dann hinzuzufügen/zu ändern, wenn sich das zugrunde liegende Dokument ändert. Dies kann mit einem observeChanges Muster geschehen. Oder Sie könnten Ihr Datenmodell etwas denormalisieren, um all diese Verknüpfungen zu vermeiden.
  2. Sie ändern das DOM, indem Sie Ereignisse mit jQuery an mehrere Selektoren anhängen, anstatt Meteor Event-Handler zu verwenden. Dies geschieht auch in Ihrem Autorun, was bedeutet, dass Sie dieselben Ereignisse wiederholt denselben DOM-Objekten zuordnen.
  3. Sie verwenden viele Session Variablen und Sie verwenden sie wiederholt. Diese können langsam sein, da sie lokalen Browserspeicher verwenden. Sie sollten .get() solche Daten nur einmal in eine lokale Variable eingeben und sich dann von da an auf die lokale Variable beziehen.
  4. Stellen Sie sicher, dass Sie nur Felder in Ihre Schedules Publikation einfügen, auf die sich Ihr Code tatsächlich auf dem Client bezieht. Der Rest ist Overhead.