我想根据我的收藏品中的数据创建图表。 这个数据由我的路由器设置中的聚合拉取调用,并由template.rendered函数中的Session.data设置。
Meteor.call放在waitOn函数中。 如果渲染模板,则不存在数据。
我尝试了onBeforeAction,action,setTimeout ......但我不能设置渲染函数等到调用数据出现。
我尝试在我的RouteController和Router.route上的action,waitOn和data函数中设置onBeforeAction和onRun挂钩中的调用。
我用setTimeout包装了我的渲染代码,但它没有用。
Router.configure({
layoutTemplate: 'global',
loadingTemplate: 'loading',
notFoundTemplate: 'notFound',
});
Router.onBeforeAction("loading");
在我的全局路由设置中设置。
我已经尝试过以下解决方案:
question 23575826
question 26198531
https://github.com/EventedMind/iron-router/issues/554#issuecomment-39002306
在最后的日子里更多。
是否有任何建议我的路由器设置或其他方法来解决此问题并及时获取数据? 我考虑选择npm-modules光纤/未来,但我不知道如何嵌入和使用它们。
我的设置: 流星是v1.0.2.1
router.js 拥有自己的控制器
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函数更改为:
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
结果是:我的调用循环。
我测试了@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();
};
})
[...]
})
];
},
两个结果都是:我的呼叫循环。
答案 0 :(得分:0)
您在这里遗漏的是waitOn
您需要返回一个对象列表,每个对象都有ready
方法作为被动数据源。不幸的是,Meteor.call
不会返回此类对象,但例如Meteor.subscribe
会返回。
您可以使用以下包装器,但请确保首先将reactive-var
包添加到项目中。
function waitUntilDone (action) {
var isReady = new ReactiveVar(false);
action(function () {
isReady.set(true);
});
return {
ready: function () {
return isReady.get();
}
};
}
现在,不要像这样返回Meteor.call
的结果列表
waitOn: function () {
return [
Meteor.call(..., function () { ... }),
Meteor.call(..., function () { ... }),
// ...
]
}
以下列方式使用上面的包装器
waitOn: function () {
return [
waitUntilDone(function(done) {
Meteor.call(..., function () {
// ...
done();
}),
}),
// ...
]
}
答案 1 :(得分:0)
更新:经过几天的测试后,我将功能更改为Meteor.publish
而不是Meteor.method
,因此waitOn
功能正在运行。
我没有意识到这也适用于发布。聚合db-calls的示例都是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
函数可以正常工作,但如果没有手动刷新模板,数据就不会在我的图表中呈现。