I'm receiving a very weird error:
Exception from sub sda4Ho8DT6MXTKjvb TypeError: Object #<Object> has no method 'find'
I20140728-11:22:25.248(-4)? at null._handler (app/server/publications.js:4:18)
This is my code. Very simple pub/sub. No idea why I get this error.
publications.js
Meteor.publish('assets', function() {
//query = query || {};
//query.removed = false;
return Assets.find();
});
assets_col.js
Assets = new Meteor.Collection('assets');
router.js
waitOn: function() {
return Meteor.subscribe('assets');
}
Related
I have started a new project and having a push error in my function. I am not sure where the error is coming from
exports.ObserveStatus = functions.database.ref("/patients/{patient_id}/status/current").onWrite((event) => {
const snap = event.data;
const patient_id = event.params.patient_id;
if (snap.exists() && snap.child("status_id").changed()) {
let p_timer = {
status_id: snap.previous.child("status_id"),
started: snap.previous.child("started"),
ended: admin.database.ServerValue.TIMESTAMP
};
return admin.database().ref(`/patients/${patient_id}/status/previous`).push(p_timer);
}
This is the error I am getting in the console:
Error: Firebase.push failed: first argument contains a function in
property
'patients.-KpZ9wyqIrlTafE1sIHL.status.previous.status_id.app.firebaseInternals_.firebase_.credential.cert'
with contents: function (serviceAccountPathOrObject) {
var stringifiedServiceAccount = JSON.stringify(serviceAccountPathOrObject);
if (!(stringifiedServiceAccount in globalCertCreds)) {
globalCertCreds[stringifiedServiceAccount] = new credential_1.CertCredential(serviceAccountPathOrObject);
}
return globalCertCreds[stringifiedServiceAccount];
}
at Error (native)
It is missing when getting references snap.previous.child
.val()
It should be
snap.previous.child("started").val()
I've been stuck on this for way too long. Can anyone help show me why my wrapasync method is returning as "undefined"? I'm trying to make a call to Facebook api and have used a php connector that my meteor app should use to talk to the Facebook PHP SDK. My app talks to the my php file and returns simple functions. But when I actually call the external service it comes back as undefined, although when I run the php function in php it comes out fine and returns expected results. Here's the code, everything is server-side:
var phpAsync = function() {
var execPhp = Meteor.npmRequire('exec-php');
execPhp('C:/xampp/htdocs/xampp/Facebook/file.php', function(error, php, output){
// php now contain user defined php functions.
php.me( function(error, result, output, printed){
// `result` is return value of `my_own_php_function` php function.
console.log(result);
return result;
});
});
};
Meteor.methods({
phpConnect: function () {
var phpSync = Meteor.wrapAsync(phpAsync);
var result = phpSync();
console.log(result);
return result
}
});
The function that is passed in to Meteor.wrapAsync should have callback as the final parameter. From the docs,
Wrap a function that takes a callback function as its final parameter.
The signature of the callback of the wrapped function should be
function(error, result){}
So you should do something like this,
var phpSync = function() {
var execPhp = Meteor.npmRequire('exec-php');
var execPhpSync = Meteor.wrapAsync(execPhp);
var php = execPhpSync('C:/xampp/htdocs/xampp/Facebook/file.php');
php.meSync = Meteor.wrapAsync(php.me);
var result = php.meSync();
console.log(result);
return result;
};
Meteor.methods({
phpConnect: function () {
var result = phpSync();
console.log(result);
return result;
}
});
OR
if you want other stuff like output and printed then you do it like this
var phpAsync = function(cb) {
var execPhp = Meteor.npmRequire('exec-php');
execPhp('C:/xampp/htdocs/xampp/Facebook/file.php', function(error, php, output){
//IMPORTANT: you need to call php.me only if there is no error
// php now contain user defined php functions.
php.me( function(error, result, output, printed){
// `result` is return value of `my_own_php_function` php function.
if (typeof cb === "function) {
cb(error, {
result: result,
output: output,
printed: printed
});
}
});
});
};
Meteor.methods({
phpConnect: function () {
var phpSync = Meteor.wrapAsync(phpAsync);
var result = phpSync();
console.log(result.result, result.output, result.printed);
return result.result;
}
});
My angular controller looks like this:
angular.module("campos").controller("HomeCtrl", ['$scope', '$meteor', '$rootScope', '$state', '$modal',
function ($scope, $meteor, $rootScope, $state, $modal) {
// $scope.users = $meteor.collection(Meteor.users, false).subscribe('users');
$meteor.autorun($scope, function () {
$scope.$meteorSubscribe('myOrgnization', 'crown').then(function () {
$scope.organization.forEach(function (org) {
console.log(org._id);
});
},
function (error) {
console.log(error);
});
});
$scope.organization = $meteor.collection(function(){
return Organizations.find({});
});
}
]);
The server code looks like :
Meteor.publish('myOrgnization', function(org){
return Organizations.find({
'code' : org
});
});
The client controller finished properly, from the console I can get the the record id properly. However, I got an exception thrown out:
TypeError: undefined is not a function
at http://localhost:8026/packages/urigo_angular.js?de756130fe1ce5aaa41d3967997c1b2090bcdd1b:390:12
at Array.forEach (native)
at Function._.each._.forEach (http://localhost:8026/packages/underscore.js?46eaedbdeb6e71c82af1b16f51c7da4127d6f285:149:11)
at diffArray (http://localhost:8026/packages/urigo_angular.js?de756130fe1ce5aaa41d3967997c1b2090bcdd1b:388:5)
at updateCollection (http://localhost:8026/packages/urigo_angular.js?de756130fe1ce5aaa41d3967997c1b2090bcdd1b:1310:3)
at http://localhost:8026/packages/urigo_angular.js?de756130fe1ce5aaa41d3967997c1b2090bcdd1b:1154:11
at http://localhost:8026/packages/angular_angular.js?feeaf4750c9fd3ceafa9f712f99a21ee6fef9b41:17819:31
at completeOutstandingRequest (http://localhost:8026/packages/angular_angular.js?feeaf4750c9fd3ceafa9f712f99a21ee6fef9b41:5529:10)
at http://localhost:8026/packages/angular_angular.js?feeaf4750c9fd3ceafa9f712f99a21ee6fef9b41:5806:7
home.ng.js:8 dPmZoCeJ9YbKxKA4u
It seems coming from angular defer, but I think I am following the subscribe syntax properly ? even I change it to use $meter.subscribe, it throws the same exception.
Any help will be much appreciated.
Thanks in advance.
You should assign the $scope collection after the promise returns:
$scope.$meteorSubscribe('myOrgnization', 'crown').then(function () {
$scope.organization = $scope.$meteorCollection(function(){
return Organizations.find({});
});
});
I would also suggest passing an object for your publish arguments:
$scope.$meteorSubscribe('myOrginization', {arg1: 'crown'}).then(...)
Then of course on the server you would get:
Meteor.publish('myOrgnization', function(org){
return Organizations.find({
'code' : org.arg1
});
});
I found this error in the server console:
Exception in defer callback: TypeError: undefined is not a function
at packages/ddp/livedata_server.js:1054:1
at Array.forEach (native)
at Function..each..forEach (packages/underscore/underscore.js:105:1)
at [object Object]._.extend._callStopCallbacks (packages/ddp/livedata_server.js:1053:1)
at [object Object]._.extend._deactivate (packages/ddp/livedata_server.js:1043:1)
at packages/ddp/livedata_server.js:803:1
at Function..each..forEach (packages/underscore/underscore.js:113:1)
at [object Object]._.extend._deactivateAllSubscriptions (packages/ddp/livedata_server.js:802:1)
at packages/ddp/livedata_server.js:444:1
at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1)
And here the code I use:
/* Source: http://phucnguyen.info/blog/how-to-publish-to-a-client-only-collection-in-meteor/ */
var subs = {};
Meteor.publish(
// THROW AN 'EXCEPTION IN DERFER CALLBACK: ...'
'helperPublication',
function () {
var subscription = this;
subs[subscription._session.id] = subscription;
Datasets.find().map(function (dataset) {
subscription.added(
'subdatasets',
dataset._id,
{
name: dataset.name,
data: [], // To avoid "Uncaught TypeError: Cannot read property 'length' of undefined" error on load
peaks: [] // Idem
}
)
});
subscription.onStop();
subscription.ready()
});
You can find the whole app in the following meteorpad: http://meteorpad.com/pad/6NDneym2qEW7pF9JM/ClearChrom
Ok, So with that info; I think the best way to go about doing this is to have separate collection for that data. Because then you can easily change how much data should be displayed. The publication for that collection could look like this:
Meteor.publish('data', function publishData (limit) {
return DataCollection.find({}, {
fields: {
name: 1,
data: 1,
peaks: 1
},
limit: limit
})
});
Note that the callback of the publication takes an argument limit. You can now subscribe to it like this:
Meteor.subscribe('data', 3)
And whenever you need more data you can just:
Meteor.subscribe('data', 6)
So this solution is reactive and very clean (in my opinion at least).
I also checked your existing script:
var subs = {};
Meteor.publish(
'helperPublication',
function (limit) {
var subscription = this;
subs[subscription._session.id] = subscription;
// I'd use forEach here, because you're not modifying the document
Datasets.find().forEach(function (doc) {
subscription.added(
'subdatasets',
doc._id,
{
name: doc.name,
// Whith the slice function you can get a subset of the data array
data: doc.data.slice(0, limit),
peaks: doc.peaks
}
)
});
// Calling `subscription.onStop` without an argument doesn't do anything
// Except maybe through an error
subscription.onStop(function () {
// clean the subscription from subs again
delete subs[subscription._session.id];
});
// This shouldn't be necessary.
// subscription.ready()
});
There are some issues with this still. For one thing I'd advise you to try avoiding meteor attributes with an underscore in front. They might be removed or changed in future releases.
The page still renders as it should, but this appears in my console log.
Exception in callback of async function: TypeError: Cannot read
property 'username' of undefined
at null. (http://localhost:3000/router.js?39194109cc7760190c519a386d66c807ba19230c:48:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRerun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:520:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:505:11)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at dispatch (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:448:3)
Which points to the line indicated below:
var OnBeforeActions = {
loginRequired: function() {
if (!Meteor.userId()) {
this.render('hello');
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
only: ['home']
});
Router.route('/', function() {
// this.render('homepage');
Router.go('/users/' + Meteor.userId());
});
Router.route('/users/:user_id', function() {
this.render('home', {
data: {
username: Meteor.users.findOne({
_id: this.params.user_id
}).username, // THIS LINE HERE
}
});
});
The idea is to redirect the user to his page if he is already logged in - and it appears to work as it should, but why am I getting this?
When the browser loads initially there will not be any data available (all the collections will be empty - until they are downloaded. Thus the result of the query Meteor.users.findOne({_id: this.params.user_id}) will be undefined.
This is the reason you can't read username out of undefined.
Since the query will re-run/it is reactive you just need to take account when it is null and it will sort itself out. user.username is only read if user is not null:
Router.route('/users/:user_id', function() {
var user = Meteor.users.findOne({_id :this.params.user_id});
this.render('home', {
data: {
username: user && user.username
}
});
});