IronRouter:在waitOn中的调用完成之前呈现模板 [英] IronRouter: template is rendered before call in waitOn is finished

查看:40
本文介绍了IronRouter:在waitOn中的调用完成之前呈现模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想基于我的收藏中的数据创建图表. 这些数据由我的路由器设置中的汇总提取调用,并由template.rendered函数中的Session.data设置.

I want to create charts based on data from my collection. This data is called by an aggregate pull in my router-settings and set by Session.data in the template.rendered function.

Meteor.call放置在waitOn函数中. 如果呈现了模板,则数据不存在.

The Meteor.call is placed in the waitOn-function. If the template is rendered, the data is not present.

我尝试了onBeforeAction,action,setTimeout ...,但是我无法将渲染功能设置为等到调用数据出现后再使用.

I tried onBeforeAction, action, setTimeout... but i can't set the render-function to wait until the call-data is present.

我试图在onBeforeAction和onRun挂钩中设置调用,在动作中,在RouteController和Router.route上都设置了waitOn和data函数.

I tried to set the calls in the onBeforeAction and onRun hooks, in the action, waitOn and data functions both on my RouteController and Router.route.

我用setTimeout包装了呈现的代码,但是没有用.

I wrapped my rendered-code with setTimeout, but it didn't work.

Router.configure({
  layoutTemplate: 'global',
  loadingTemplate: 'loading',
  notFoundTemplate: 'notFound',
});
Router.onBeforeAction("loading");

是在我的全局路由设置中设置的.

is set in my global routing settings.

我已经尝试了以下解决方案:
问题23575826
问题26198531
https://github.com/EventedMind/iron-router/issues/554 #issuecomment-39002306
在过去的日子里还有更多.

I've already tried following solutions:
question 23575826
question 26198531
https://github.com/EventedMind/iron-router/issues/554#issuecomment-39002306
and more in the last days.

是否对我的路由器设置有任何建议,或者是否有其他方法可以解决此问题并及时呈现数据? 我考虑选择npm-modules光纤/期货,但我不知道如何嵌入和使用它们.

Is there any suggestion for my router settings or another way to solve this problem and get the data rendered in time? I consider to pick the npm-modules fiber/future, but i've no idea how to embed and use them.

我的设置: 流星是v1.0.2.1

My settings: Meteor is v1.0.2.1

router.js (带有自己的控制器)

router.js with own controller

StatsController = RouteController.extend({
  template: 'statsShow',
  waitOn: function () {
    return [
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'SellerOne', 2014, function(error, result){
        if(!error)
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']); 
      }),
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'SellerTwo', 2014, function(error, result){
        if(!error)
          Session.set('info3Units', result['units']);
          Session.set('info3Volumes', result['volumes']); 
      }),
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'SellerThree', 2014, function(error, result){
        if(!error)
          Session.set('avaUnits', result['units']);
          Session.set('avaVolumes', result['volumes']);  
      })
    ];
  },
  data: function () {
    return Books.findOne({_id: this.params._id});
  },
  action: function () {
    if (!this.ready()) {
      this.render('Loading');
    } else {
      this.render(); 
    }
  }
});

Router.route('stats/show/', {
  name: 'stats.show',
  controller: 'TestController'
});

methods.js

Meteor.methods({
  saleGetDataPerYear: function(bookId, seller, year) {
    var sellerUnits = [];
    var sellerVolumes = [];
    var resultData = {};

    var pipeline = [
      {
        $match : { bookId: bookId, salesSeller: seller, salesYear: year }
      },
      {
        $group : {
          _id : {
            sale: { "salesMonth": "$salesMonth" }
          },
          units: { $sum: "$salesUnits" },
          volumes: { $sum: "$salesVolumes" },
          month: { $first: "$salesMonth" },
          year: { $first: "$salesYear" },
          seller: { $first: "$salesSeller" }   
        }
      },
      {
        $sort : {
          month: 1
        }
      }      
    ];    
    result = Sales.aggregate(pipeline);              

    if(result){
      sellerUnits.push(seller);
      sellerVolumes.push(seller);
      result.forEach(function(data){
        sellerUnits.push(data.units);
        sellerVolumes.push(data.volumes);
      });
      resultData['units'] = sellerUnits;
      resultData['volumes'] = sellerVolumes;
    }

    if(resultData){
      return resultData;     
    } else {
      throw new Meteor.Error("no-data", "No Data collected");
    }
  }

模板

//-- template rendered functions
Template.statsShow.rendered = function(){ 
    var chartUnitsBrockhaus = Session.get('brockhausUnits');
    var chartUnitsInfo3 = Session.get('info3Units');
    var chartUnitsAva = Session.get('avaUnits');
    var chartUnitsSumme = Session.get('sumUnits');

    console.log(chartUnitsBrockhaus);

    var chartUnits = c3.generate({
      bindto: this.find('.chartUnits'),
      data: {
        columns: [
          chartUnitsBrockhaus,
          chartUnitsInfo3,
          chartUnitsAva,
          chartUnitsSumme   
        ],
        type: 'bar',
        types: {
          Summe: 'spline',
        },
      },
      axis: {
        x: {
          type: 'category',
            categories: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']
        }
      },
      bar: {
        width: {
          ratio: 0.5
        }
      }
    });       
};

包装

accounts-password             1.0.5
accounts-ui                   1.1.4 
alanning:roles                1.2.13
aldeed:autoform               4.2.2 
aldeed:autoform-select2       1.0.3
aldeed:collection2            2.3.1
aldeed:simple-schema          1.3.0 
anti:fake                     0.4.1
chrismbeckett:fontawesome4    4.2.2 
coffeescript                  1.0.5 
ctjp:meteor-bootstrap-switch  3.3.1_1 
dburles:collection-helpers    1.0.2 
francocatena:status           1.0.3  
iron:router                   1.0.7 
lepozepo:accounting           1.0.0 
less                          1.0.12  
matteodem:easy-search         1.4.6  
meteor-platform               1.2.1 
meteorhacks:aggregate         1.1.0   
mrt:jquery-csv                0.7.1  
natestrauser:select2          3.5.1  
nemo64:bootstrap              3.3.1_1 
ongoworks:security            1.0.1  
peerlibrary:xml2js            0.4.4_3 
peernohell:c3                 1.1.2 
sacha:spin                    2.0.4  
service-configuration         1.0.3  
underscore                    1.0.2 
zimme:select2-bootstrap3-css  1.4.1

修改
正如@DavidWeldon提到的,我将我的waitOn函数更改为:

Edit
as @DavidWeldon mentioned i changed my waitOn function to:

waitOn: function () {
  return [
    // first call
    Meteor.callWithReady('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Brockhaus', 2014, function(error, result){
      if(!error) {
        console.log(result); //debug
        Session.set('brockhausUnits', result['units']);
        Session.set('brockhausVolumes', result['volumes']);
      };          
    }),
    // second call
    Meteor.callWithReady('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Info3', 2014, function(error, result){
      if(!error) {
        console.log(result); //debug
        Session.set('brockhausUnits', result['units']);
        Session.set('brockhausVolumes', result['volumes']);
      };            
    }),
    // third call
    Meteor.callWithReady('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'AVA', 2014, function(error, result){
      if(!error) {
        console.log(result); //debug
        Session.set('brockhausUnits', result['units']);
        Session.set('brockhausVolumes', result['volumes']);
      };            
    }),
    // fourth call
    Meteor.callWithReady('saleGetSumDataPerYear', 'nYWpgxR3kEY8kwBkA', 2014, function(error, result){
      if(!error) {
        console.log(result); //debug
        Session.set('sumUnits', result['units']);
        Session.set('sumVolumes', result['volumes']); 
      }           
    })   
  ];
},

并在/lib下添加 test.coffee :

_.defaults Meteor,
  callWithReady: (method, options...) ->
    dep = new Deps.Dependency
    ready = false

    lastOption = _.last options
    if _.isFunction lastOption
      Meteor.apply method, _.initial(options), (err, result) ->
        lastOption err, result
        ready = true
        dep.changed()
    else
      Meteor.apply method, options, (err, result) ->
        ready = true
        dep.changed()

    ready: ->
      dep.depend()
      ready

结果是:我的电话循环.

result is: my calls loop.

我测试了@apendua的答案.

I tested the answer from @apendua.

function waitUntilDone (action) {
  var isReady = new ReactiveVar(false);
  action(function () {
    isReady.set(true);
  });
  return {
    ready: function () {
      return isReady.get();
    }
  };
}

waitOn: function () {
  return [
    // first call
    waitUntilDone(function(done) {
      Meteor.callWithReady('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Brockhaus', 2014, function(error, result){
        if(!error) {
          console.log(result); //debug
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']);
        };
        done();             
      })
    }),
    // second call
    waitUntilDone(function(done) {
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Info3', 2014, function(error, result){
        if(!error) {
          console.log(result); //debug
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']);
          done();
        };            
      })
    }),
    // third call
    waitUntilDone(function(done) {
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'AVA', 2014, function(error, result){
        if(!error) {
          console.log(result); //debug
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']);
          done(); 
        };            
      })
    }),
    // fourth call
    waitUntilDone(function(done) {
      Meteor.call('saleGetSumDataPerYear', 'nYWpgxR3kEY8kwBkA', 2014, function(error, result){
        if(!error) {
          console.log(result);
          Session.set('sumUnits', result['units']);
          Session.set('sumVolumes', result['volumes']); 
          done(); 
        }           
      })
    })   
  ];
},

waitOn: function () {
  return [
    // first call
    waitUntilDone(function(done) {
      Meteor.callWithReady('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Brockhaus', 2014, function(error, result){
        if(!error) {
          console.log(result); //debug
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']);
        };
        done();             
      }),
      Meteor.call('saleGetDataPerYear', 'nYWpgxR3kEY8kwBkA', 'Info3', 2014, function(error, result){
        if(!error) {
          console.log(result); //debug
          Session.set('brockhausUnits', result['units']);
          Session.set('brockhausVolumes', result['volumes']);
          done();
        };            
      })
      [...]
    })   
  ];
},

两个结果都是:我的通话循环.

both results are: my calls loop.

推荐答案

更新:经过几天的测试,我将功能更改为Meteor.publish而不是Meteor.method,因此waitOn功能现在可以使用了. 我没有意识到这也适用于发布.汇总数据库调用的示例全都用Meteor.method.

Update: After some days of testing i changed the functions to Meteor.publish instead of Meteor.method so the waitOn function is now working. i didn't realise that this also work with publish. The examples for aggregate db-calls are all with Meteor.method.

publications.js

Meteor.publish('saleGetAllDataPerYear', function(bookId, year) {
  self = this;

  var pipeBH = [];
  var resultBH = '';
  var unitsBH = [];
  var volumesBH = [];
  var monthBH = [];

  var pipeI3 = [];
  var resultI3 = '';
  var unitsI3 = [];
  var volumesI3 = [];
  var monthI3 = [];

  var pipeAVA = [];
  var resultAVA = '';
  var unitsAVA = [];
  var volumesAVA = [];
  var monthAVA = [];

  var pipeSum = [];
  var resultSum = '';
  var unitsSum = [];
  var volumesSum = [];
  var monthSum = [];

  // Set Brockhaus data  
  pipeBH = [
    { $match : { bookId: bookId, salesSeller: 'Brockhaus', salesYear: year } },
    { $group : { _id : { sale: { "salesMonth": "$salesMonth" } }, 
        units: { $sum: "$salesUnits" }, volumes: { $sum: "$salesVolumes" }, month: { $first: "$salesMonth" }, year: { $first: "$salesYear" }, seller: { $first: "$salesSeller" }   
      }
    },
    { $sort : { month: 1 } }
  ];
  resultBH = Sales.aggregate(pipeBH);

  if(resultBH != ''){
    unitsBH.push('Brockhaus');
    volumesBH.push('Brockhaus');
    resultBH.forEach(function(data){
      unitsBH.push(data.units);
      volumesBH.push(data.volumes);
      monthBH.push(data.month);
    });
    self.added('stats', Random.id(), {seller: 'Brockhaus', units: unitsBH, volumes: volumesBH, month: monthBH, year: year});
    self.ready();
  } else {
    self.ready();
  }

  // Set Info3 data
  pipeI3 = [
    { $match : { bookId: bookId, salesSeller: 'Info3', salesYear: year } },
    { $group : { _id : { sale: { "salesMonth": "$salesMonth" } }, 
        units: { $sum: "$salesUnits" }, volumes: { $sum: "$salesVolumes" }, month: { $first: "$salesMonth" }, year: { $first: "$salesYear" }, seller: { $first: "$salesSeller" }   
      }
    },
    { $sort : { month: 1 } }
  ];
  resultI3 = Sales.aggregate(pipeI3);

  if(resultI3 != ''){
    unitsI3.push('Info3');
    volumesI3.push('Info3');
    resultI3.forEach(function(data){
      unitsI3.push(data.units);
      volumesI3.push(data.volumes);
      monthI3.push(data.month);
    });
    self.added('stats', Random.id(), {seller: 'Info3', units: unitsI3, volumes: volumesI3, month: monthI3, year: year});
    self.ready();
  } else {
    self.ready();
  }

  // Set AVA data
  pipeAVA = [
    { $match : { bookId: bookId, salesSeller: 'AVA', salesYear: year } },
    { $group : { _id : { sale: { "salesMonth": "$salesMonth" } }, 
        units: { $sum: "$salesUnits" }, volumes: { $sum: "$salesVolumes" }, month: { $first: "$salesMonth" }, year: { $first: "$salesYear" }, seller: { $first: "$salesSeller" }   
      }
    },
    { $sort : { month: 1 } }
  ];
  resultAVA = Sales.aggregate(pipeAVA);

  if(resultAVA != ''){
    unitsAVA.push('AVA');
    volumesAVA.push('AVA');
    resultAVA.forEach(function(data){
      unitsAVA.push(data.units);
      volumesAVA.push(data.volumes);
      monthAVA.push(data.month);
    });
    self.added('stats', Random.id(), {seller: 'AVA', units: unitsAVA, volumes: volumesAVA, month: monthAVA, year: year});
    self.ready();
  } else {
    self.ready();
  }

  // Set Sum data
  pipeSum = [
    { $match : { bookId: bookId, salesYear: year } },
    { $group : { _id : { sale: { "salesMonth": "$salesMonth" } }, 
        units: { $sum: "$salesUnits" }, volumes: { $sum: "$salesVolumes" }, month: { $first: "$salesMonth" }, year: { $first: "$salesYear" }, seller: { $first: "$salesSeller" }   
      }
    },
    { $sort : { month: 1 } }
  ];
  resultSum = Sales.aggregate(pipeSum);

  if(resultSum != ''){
    unitsSum.push('Summe');
    volumesSum.push('Summe');
    resultSum.forEach(function(data){
      unitsSum.push(data.units);
      volumesSum.push(data.volumes);
      monthSum.push(data.month);
    });
    self.added('stats', Random.id(), {seller: 'Summe', units: unitsSum, volumes: volumesSum, month: monthSum, year: year});
    self.ready();
  } else {
    self.ready();
  }
});

router.js

waitOn: function () {
  year = Number(Session.get('year'));
  return [
    Meteor.subscribe('saleGetAllDataPerYear', this.params._id, year),
    Meteor.subscribe('getStats')
  ];
},

感谢@JeremyS的另一种启发.听起来这是更好的解决方案,因为现在waitOn函数可以工作了,但是如果没有手动刷新模板,数据就不会在我的图表中呈现.

Thanks to @JeremyS for the inspiration on another way. That sounds like the better solution because now the waitOn function works but the data is not rendered in my chart without manual refresh of my template.

这篇关于IronRouter:在waitOn中的调用完成之前呈现模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆