Can someone explain this thing to me: if I'm getting data from a collection in browser's console, it works fine, but at the same time when a template (which uses the same collection) is being rendered it throws an exception as the query result is empty. What am I doing wrong?
Hubs = new Meteor.Collection("hubs");
Meteor.subscribe("hubs");
Template.thread.posts = function() {
var hubName = 'foo',
thread = Session.get("currentThread"),
hub = Hubs.find({ name: hubName }).fetch()[0];
//throws: "Uncaught TypeError: Cannot read property 'threads' of undefined "
return hub.threads[thread].posts;
}
//this being executed in browser's console yeilds an object:
Hubs.find({name: 'foo'}).fetch()[0]
Other templates that use the same collection work fine, though
When Meteor initially loads on the browser it wont yet have the data from the collections from the server.
It takes a very short amount of time for them to be available. So you just need to handle the case where there is no result provided. When the data arrives reactivity should update all your templates with the new data.
You can use something like:
hub = Hubs.findOne({ name: hubName })
if(hub) return hub.threads[thread].posts;
findOne is a shorter version of find().fetch[0]. So if there isn't a result i.e null nothing is returned and .threads wont be read so there wouldn't be an exception.
Related
I was wondering how I can query documents from a firestore collection from an array of ID's? I only want the documents in the collection that are in the array of ID's. I looked at another answer and think my approach is correct, however, I am getting an error.
(node:15105) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'data' of undefined
> at /Users/username/SideProjects/projectname/functions/index.js:40:38
> at processTicksAndRejections (internal/process/task_queues.js:95:5)
The error happens because the function is not finding any documents in the collection from that array of ID's. However, I double-checked the database and know that there are documents in the collection with ID's from the array.
const admin = require('firebase-admin')
....
let feedItems = db.collection(feedItemsCollection)
feedItemsList = feedItems.where(admin.firestore.FieldPath.documentId(), 'in', ['HPOorsSnbHpTYwwXxfWw']).get().then(snapshot2 => {
console.log(admin.firestore.FieldPath.documentId())
console.log("In feed Items")
//console.log(feedItemIds)
console.log(snapshot2[0])
//error happens on this line because snapshot2[0] returns undefined
console.log(snapshot2[0].data())
})
Snapshot2[0] returns undefined which I'm assuming means that no data was returned. I think I'm not properly calling documentId(), but don't know the fix.
There "maybe" two problems with your code. Follow both points to make sure things are working
Data inside snapshot2 maybe empty
You'll first have to fix your code to test this theory. You're not accessing data from snapshot2 correctly. To do it right, one way is this:
// `snapshot2` will have a `docs` property that you can leverage
const snapshot2Data = snapshot2.docs.map((doc) => doc.data());
.documentId() may not be doing what it's supposed to (as you said)
To test this theory, check if snapshot2Data is empty. Run :
console.log(snapshot2Data); // what do you get ?
If no, it's not empty and you got data back, then you're all set. Nothing more to do
If yes, it is empty, then run :
console.log(admin.firestore.FieldPath.documentId()); // what do you get ?
Did you get back a string? If no, then we have another problem. You'll need to take a closer look at your firebase-admin setup, as well.
Problem
In a social media app I am making with react native and firebase, I am trying to grab the number of comments a post has using the snapshot function of a variable I have saved on my servers, then I am going to add one to this variable when a user adds a new comment. My code to do so is right here:
firebase.database().ref('posts').child(this.state.passKey).update({
comments: firebase.database().ref('posts/'+this.state.passKey).child('comments').snapshot.val() + 1
})
When I actually run this code, I get an error saying:
Reference.child failed: First argument was an invalid path = "undefined".
Paths must be non-empty strings and can't contain ".","#","$","[", or "["
At first I thought this might be that the "this.state.passKey" wasn't actually passing the key, but putting in a key I copied from the server didn't fix the problem.
My Server
-
To get the comments of particular post you should do like this
let postId='someId'
postRef=`/posts/${postId}`
firebase.database().ref(postRef).once("value", dataSnapshot => {
comment=dataSnapshot.val().comments
});
It looks like you're expecting this bit of code to query the database:
firebase.database().ref('posts/'+this.state.passKey).child('comments').snapshot.val() + 1
Unfortunately, it doesn't work that way. There's no snapshot property on a database Reference object returned by child() or ref().
Instead, you'll need to query the database at that reference, then when you're called back with its value, you can apply it elsewhere.
var ref = firebase.database().ref('posts/'+this.state.passKey+'/comments')
ref.once('value', function(snapshot) {
// use the snapshot here
})
I created a small sample application using VueJs and created a C# REST API to store and retrieve data in a SQL Server back end.
For testing, I created a simple web page with a form to create a "note". The note is stored by the following function, 'saveData()':
saveData()
{
let promiseStack = [];
var jsondata = JSON.stringify(this.note);
promiseStack.push(this.$http.post('REST_API/note', jsondata));
Promise.all(promiseStack).then(data =>
{
this.$http.get('REST_API/note');
this.$router.push({ name: 'viewnotes', params: { id: data[0].body.id }})
}, error =>
{
console.log(error);
});
}
I tried to use a promise to wait until the 'store' operation in the backend is complete, and issue a GET request to retrieve all notes once the promise is fulfilled.
However, the get request inside the promise doesn't return any data. If I issue the get request manually later one, I retrieve the data that was stored previously.
So I had look into the C# REST API. There are currently two functions: createNote(...), getAllNotes(...). I used a StreamWriter to log to the filesystem when these functions are called, using milisecond precision. What I see is that 'createNote' is called after 'getAllNotes'. So I suspect that the API is working correctly, but something with the way I'm using promises seems to be awfully wrong.
Maybe somebody has a hint?
UPDATE
I know that the GET request doesn't return any data by using the developer toolbar in Chromium. The response is empty
The developer toolbar in the network tab shows that the requests are submitted in the correct order, so the "POST" request is issued first
It seems I found the problem. I had a 'href' tag in my 'Save' link, which triggered an early routing. The intended 'POST' and 'GET' were fired correctly, but there was another 'GET' inbetween somewhere because of the 'href' tag in the link, even though it was empty.
I removed the tag, now it works as intended.
Only at the checkout and on individual product pages I am getting the following error in the console log:
VM35594:1 Uncaught SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at run (layout.min.js:9)
at app.min.js:1
at main.min.js:2
at Object.execCb (require.min.js:112)
at Module.check (require.min.js:56)
at Module.<anonymous> (require.min.js:72)
at require.min.js:11
at require.min.js:74
at each (require.min.js:3)
I am using a one page checkout extension, but when I disable that the error still shows. I thought it might had something to do with the reviews on the product page (as I moved the reviews out of the tabs), but undoing that change didn't fix the error on the product pages.
Try this in the console:
JSON.parse(undefined)
Here is what you will get:
Uncaught SyntaxError: Unexpected token u in JSON at position 0
at JSON.parse (<anonymous>)
at <anonymous>:1:6
In other words, your app is attempting to parse undefined, which is not valid JSON.
There are two common causes for this. The first is that you may be referencing a non-existent property (or even a non-existent variable if not in strict mode).
window.foobar = '{"some":"data"}';
JSON.parse(window.foobarn) // oops, misspelled!
The second common cause is failure to receive the JSON in the first place, which could be caused by client side scripts that ignore errors and send a request when they shouldn't.
Make sure both your server-side and client-side scripts are running in strict mode and lint them using ESLint. This will give you pretty good confidence that there are no typos.
As #Seth Holladay #MinusFour commented, you are parsing an undefined variable.
Try adding an if condition before doing the parse.
if (typeof test1 !== 'undefined') {
test2 = JSON.parse(test1);
}
Note: This is just a check for undefined case. Any other parsing issues still need to be handled.
localStorage.clear()
That'll clear the stored data. Then refresh and things should start to work.
Your app is attempting to parse the undefined JSON web token. Such malfunction may occur due to the wrong usage of the local storage. Try to clear your local storage.
Example for Google Chrome:
F12
Application
Local Storage
Clear All
For me, that happened because I had an empty component in my page -
<script type="text/x-magento-init">
{
".page.messages": {
"Magento_Ui/js/core/app": []
}
}
Deleting this piece of code resolved the issue.
This is due to the interfering messages that come on to the page. There are multiple frames on the page which communicate with the page using window message event and object. few of them can be third party services like cookieq for managing cookies, or may be cartwire an e-com integration service.
You need to handle the onmessage event to check from where the messages are coming, and then parse the JSON accordingly.
I faced a similar problem, where one of the integration was passing a JSON object and other was passing a string starting with u
If you get Uncaught SyntaxError: Unexpected token u in JSON at position 0 then you could do the following quick checks:
jsObj = JSON.parse(data)
data - check the data is undefined or not
data - check the data is a valid JSON string or not
data - check the data is corrupted by unwanted whitespace or not
data = data.trim(); // remove the unwanted whitespace
jsObj = JSON.parse(data);
data - check the received data uses the correct encoding format('utf8', 'utf16le', 'ucs2') or not
fs.readFile(file, 'utf8', function(err, data) { ... });
fs.readFile(file, 'utf16le', function(err, data) { ... }); // le - little endian
fs.readFile(file, 'ucs2', function(err, data) { ... }); // kind of 'utf16le'
I had this issue for 2 days, let me show you how I fixed it.
This was how the code looked when I was getting the error:
request.onload = function() {
// This is where we begin accessing the Json
let data = JSON.parse(this.response);
console.log(data)
}
This is what I changed to get the result I wanted:
request.onload = function() {
// This is where we begin accessing the Json
let data = JSON.parse(this.responseText);
console.log(data)
}
So all I really did was change
this.response to this.responseText.
I'm attaching response data to the target of a jquery plugin when a preload option is set. It all seems to work a charm except the data I set is inaccessible. When I log $(elm).data(); I can see that the object was returned with the appropriate data set to the appropriate key. But when I try console.log($(elm).data('key')); I get undefined. I also get undefined when I try var elmData = $(elm).data(); console.dir(elmData.key);. So I'm logging the object on one line, seeing it in the console, trying to access a property I just confirmed exists and getting undefined.
Here is my function:
this.preloadData = function(folders)
{
var getString;
for(var folder in folders ){
getString = 'folder='+folders[folder]+'&uri='+uri+'&thumbSide='+options.thumbSide;
$.get(options.handler, getString,
function(response, serverStat, xhr)
{
$self.data(folder, response);
});
}//for
var $selfData = $self.data();
console.log($selfData);//Object{ editorial : "data", testingdata : 'some meaningless words'}
console.log($self.data());//Object{ editorial : "data", testingdata : 'some meaningless words'}
console.log($self.data.editorial);//undefined
console.dir($self.data('editorial'));//undefined
console.log($selfData['editorial']);//undefined
console.log($selfData.editorial);//undefined
$self.data('testingdata', 'some meaningless words');
console.log($self.data());//Object{ editorial : "data", testingdata : 'some meaningless words'}
console.log($self.data('testingdata'));//'some meaningless words'
}
I know the namespacing is too simple, I just tried to cut out as many factors as I could to try and understand why this isn't working. I'm developing in chrome but I've tried it in firefox also and get the same.
-----------------------------EDIT------------------------------------------
I understand what the problem is now. The console reflects all changes to an object that get made regardless of if they were made when the object was logged. So when I logged the object the property didn't exist yet because the response had yet to come back from the server, but the log still shows the property as existing because at some later point in the script execution it DID exist. Because primitive values aren't logged in the same way, the call to log the property shows up as undefined because it WAS undefined. If I refer to the property some seconds later, say on a click event it is defined(which is how I intended it to work anyway). I just got really caught up in debugging this function before I actually implemented it.
Can you do this?
$self.data['editorial']
try
console.log($self.data.editorial);