I'm using parse with javascript (vueJs) and i'm experiencing the following issue : when I destroy an object and then get all my data, the object is still in the result. However, if I look in my parse backend, the object has been deleted.
This is my code:
methods: {
getNotes: async function() {
console.log("\nGETTING ALL NOTES")
const Object = Parse.Object.extend("notes");
const query = new Parse.Query(Object);
query.equalTo("user", Parse.User.current());
query.descending("createdAt");
const results = await query.find();
for (let i = 0; i < results.length; i++) {
var temp = {}
const object = results[i];
temp.id = object.id
temp.note = object.get('note')
temp.date = object.get('createdAt')
this.notes.push(temp)
}
},
deleteNote: async function() {
const Object = Parse.Object.extend("notes");
const query = new Parse.Query(Object);
query.equalTo("objectId", this.selectedItem);
const results = await query.first();
if (results){
await results.destroy() // I wait for the object to be destroyed
await this.getNotes() //Then, I call (again) my function to get all notes ... but it still contains the deleted object !!
}else{
alert("There was a problem with the query")
}
}
}
Any ideas why this happens and how can I "check" when my parse database is up to date so that I can get the data again (without the removed object) ?
Related
I have this script that takes data from a JSON with almost 100 data, then uses this data to bring the weather from an API and after that, inserts this data into an object (using a for for creating my 100 objects), I would like to add the objects that have a temperature > 99 in one array and the ones that have a temperature < 99 into another I have tried this way but doesn't seem to work, sorry if it's a super fool mistake that I can't see, thanks for your help!
This is my script:
async function calcWeather(){
const info = await fetch('../json/data.json')
.then(function(response) {
return response.json()
});
for (var i in info) {
const _idOficina = info[i][0].IdOficina
const _nombreOficina = info[i][0].NombreOficinaSN
const _zona = info[i][0].Zona
const _estado = info[i][0].NombreEstado
const lat = info[i][0].latjson
const long = info[i][0].lonjson
const base = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&appid=${api_key}&units=metric&lang=sp`
fetch(base)
.then((responses) => {
return responses.json()
})
.then((data) => {
// console.log(data)
var myObject = {
Id_Oficina: _idOficina,
Latitud: data.coord.lat,
Longitud: data.coord.lon,
Ciudad: data.name,
Estado: _estado,
Zona: _zona,
Nombre_Oficina: _nombreOficina,
Temperatura: data.main.temp,
Descripcion: data.weather[0].description
};
// validation
if (myObject.Temperatura < 99){
var lstValid = [];
function pushValid(){
lstValid.push(myObject[i]);
}
pushValid();
console.log(pushValid())
}
});
}
};
Your array is local, so for every object you create new lstValid array with no previous data. The solution is to create the array before fetching the data or before the loop:
async function calcWeather(){
var lstValid = []; // HERE
const info = await fetch('../json/data.json')
.then(function(response) {
return response.json()
});
var lstValid = []; // OR HERE (ONLY ONE OF THEM)
for (...) {
...
}
You'll probably be best served by creating the array outside of that call since you're clearing it every run. Then simply add your object. Like Trincot's comment, i'm not sure what exactly you're indexing.
async function calcWeather(){
var lstValid = [];
....
if (myObject.Temperatura < 99){
lstValid[someindex] = myObject;
}
else{
lstNotValid[someOtherIndex] = myObject;
}
}
Problem Statement:
Our aim is to allocate values in the array ytQueryAppJs, which are returned from a time consuming function httpsYtGetFunc().
The values in ytQueryAppJs needs to be used many times in further part of the code, hence it needs to be done 'filled', before the code proceeds further.
There are many other arrays like ytQueryAppJs, namely one of them is ytCoverAppJs, that needs to be allocated the value, the same way as ytQueryAppJs.
The values in ytCoverAppJs further require the use of values from ytQueryAppJs. So a solution with clean code would be highly appreciated.
(I am an absolute beginner. I have never used async, await or promises and I'm unaware of the correct way to use it. Please guide.)
Flow (to focus on):
The user submits a queryValue in index.html.
An array ytQueryAppJs is logged in console, based on the query.
Expected Log in Console (similar to):
Current Log in Console:
Flow (originally required by the project):
User submits query in index.html.
The values of arrays, ytQueryAppJs, ytCoverAppJs, ytCoverUniqueAppJs, ytLiveAppJs, ytLiveUniqueAppJs gets logged in the console, based on the query.
Code to focus on, from 'app.js':
// https://stackoverflow.com/a/14930567/14597561
function compareAndRemove(removeFromThis, compareToThis) {
return (removeFromThis = removeFromThis.filter(val => !compareToThis.includes(val)));
}
// Declaring variables for the function 'httpsYtGetFunc'
let apiKey = "";
let urlOfYtGetFunc = "";
let resultOfYtGetFunc = "";
let extractedResultOfYtGetFunc = [];
// This function GETs data, parses it, pushes required values in an array.
async function httpsYtGetFunc(queryOfYtGetFunc) {
apiKey = "AI...MI"
urlOfYtGetFunc = "https://www.googleapis.com/youtube/v3/search?key=" + apiKey + "&part=snippet&q=" + queryOfYtGetFunc + "&maxResults=4&order=relevance&type=video";
let promise = new Promise((resolve, reject) => {
// GETting data and storing it in chunks.
https.get(urlOfYtGetFunc, (response) => {
const chunks = []
response.on('data', (d) => {
chunks.push(d)
})
// Parsing the chunks
response.on('end', () => {
resultOfYtGetFunc = JSON.parse((Buffer.concat(chunks).toString()))
// console.log(resultOfYtGetFunc)
// Extracting useful data, and allocating it.
for (i = 0; i < (resultOfYtGetFunc.items).length; i++) {
extractedResultOfYtGetFunc[i] = resultOfYtGetFunc.items[i].id.videoId;
// console.log(extractedResultOfYtGetFunc);
}
resolve(extractedResultOfYtGetFunc);
})
})
})
let result = await promise;
return result;
}
app.post("/", function(req, res) {
// Accessing the queryValue, user submitted in index.html. We're using body-parser package here.
query = req.body.queryValue;
// Fetching top results related to user's query and putting them in the array.
ytQueryAppJs = httpsYtGetFunc(query);
console.log("ytQueryAppJs:");
console.log(ytQueryAppJs);
});
Complete app.post method from app.js:
(For better understanding of the problem.)
app.post("/", function(req, res) {
// Accessing the queryValue user submitted in index.html.
query = req.body.queryValue;
// Fetcing top results related to user's query and putting them in the array.
ytQueryAppJs = httpsYtGetFunc(query);
console.log("ytQueryAppJs:");
console.log(ytQueryAppJs);
// Fetching 'cover' songs related to user's query and putting them in the array.
if (query.includes("cover") == true) {
ytCoverAppJs = httpsYtGetFunc(query);
console.log("ytCoverAppJs:");
console.log(ytCoverAppJs);
// Removing redundant values.
ytCoverUniqueAppJs = compareAndRemove(ytCoverAppJs, ytQueryAppJs);
console.log("ytCoverUniqueAppJs:");
console.log(ytCoverUniqueAppJs);
} else {
ytCoverAppJs = httpsYtGetFunc(query + " cover");
console.log("ytCoverAppJs:");
console.log(ytCoverAppJs);
// Removing redundant values.
ytCoverUniqueAppJs = compareAndRemove(ytCoverAppJs, ytQueryAppJs);
console.log("ytCoverUniqueAppJs:");
console.log(ytCoverUniqueAppJs);
}
// Fetching 'live performances' related to user's query and putting them in the array.
if (query.includes("live") == true) {
ytLiveAppJs = httpsYtGetFunc(query);
console.log("ytLiveAppJs:");
console.log(ytLiveAppJs);
// Removing redundant values.
ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytQueryAppJs.concat(ytCoverUniqueAppJs));
console.log("ytLiveUniqueAppJs:");
console.log(ytLiveUniqueAppJs);
} else {
ytLiveAppJs = httpsYtGetFunc(query + " live");
console.log("ytLiveAppJs:");
console.log(ytLiveAppJs);
// Removing redundant values.
ytLiveUniqueAppJs = compareAndRemove(ytLiveAppJs, ytQueryAppJs.concat(ytCoverUniqueAppJs));
console.log("ytLiveUniqueAppJs:");
console.log(ytLiveUniqueAppJs);
}
// Emptying all the arrays.
ytQueryAppJs.length = 0;
ytCoverAppJs.length = 0;
ytCoverUniqueAppJs.length = 0;
ytLiveAppJs.length = 0;
ytLiveUniqueAppJs.length = 0;
});
Unfortunately you can use the async/await on http module when making requests. You can install and use axios module . In your case it will be something like this
const axios = require('axios');
// Declaring variables for the function 'httpsYtGetFunc'
let apiKey = "";
let urlOfYtGetFunc = "";
let resultOfYtGetFunc = "";
let extractedResultOfYtGetFunc = [];
// This function GETs data, parses it, pushes required values in an array.
async function httpsYtGetFunc(queryOfYtGetFunc) {
apiKey = "AI...MI"
urlOfYtGetFunc = "https://www.googleapis.com/youtube/v3/search?key=" + apiKey + "&part=snippet&q=" + queryOfYtGetFunc + "&maxResults=4&order=relevance&type=video";
const promise = axios.get(urlOfYtGetFunc).then(data => {
//do your data manipulations here
})
.catch(err => {
//decide what happens on error
})
Or async await
const data = await axios.get(urlOfYtGetFunc);
//Your data variable will become what the api has returned
If you still want to catch errors on async await you can use try catch
try{
const data = await axios.get(urlOfYtGetFunc);
}catch(err){
//In case of error do something
}
I have just looked at the code I think the issue is how you are handling the async code in the request handler. You are not awaiting the result of the function call to httpsYtGetFunc in the body so when it returns before the promise is finished which is why you get the Promise {Pending}.
Another issue is that the array is not extractedResultOfYtGetFunc is not initialised and you may access indexes that don't exist. The method to add an item to the array is push.
To fix this you need to restructure your code slightly. A possible solution is something like this,
// Declaring variables for the function 'httpsYtGetFunc'
let apiKey = "";
let urlOfYtGetFunc = "";
let resultOfYtGetFunc = "";
let extractedResultOfYtGetFunc = [];
// This function GETs data, parses it, pushes required values in an array.
function httpsYtGetFunc(queryOfYtGetFunc) {
apiKey = "AI...MI";
urlOfYtGetFunc =
"https://www.googleapis.com/youtube/v3/search?key=" +
apiKey +
"&part=snippet&q=" +
queryOfYtGetFunc +
"&maxResults=4&order=relevance&type=video";
return new Promise((resolve, reject) => {
// GETting data and storing it in chunks.
https.get(urlOfYtGetFunc, (response) => {
const chunks = [];
response.on("data", (d) => {
chunks.push(d);
});
// Parsing the chunks
response.on("end", () => {
// Initialising the array
extractedResultOfYtGetFunc = []
resultOfYtGetFunc = JSON.parse(Buffer.concat(chunks).toString());
// console.log(resultOfYtGetFunc)
// Extracting useful data, and allocating it.
for (i = 0; i < resultOfYtGetFunc.items.length; i++) {
// Adding the element to the array
extractedResultOfYtGetFunc.push(resultOfYtGetFunc.items[i].id.videoId);
// console.log(extractedResultOfYtGetFunc);
}
resolve(extractedResultOfYtGetFunc);
});
});
});
}
app.post("/", async function (req, res) {
query = req.body.queryValue;
// Fetching top results related to user's query and putting them in the array.
ytQueryAppJs = await httpsYtGetFunc(query);
console.log("ytQueryAppJs:");
console.log(ytQueryAppJs);
});
Another option would be to use axios,
The code for this would just be,
app.post("/", async function (req, res) {
query = req.body.queryValue;
// Fetching top results related to user's query and putting them in the array.
try{
ytQueryAppJs = await axios.get(url); // replace with your URL
console.log("ytQueryAppJs:");
console.log(ytQueryAppJs);
} catch(e) {
console.log(e);
}
});
Using Axios would be a quicker way as you don't need to write promise wrappers around everything, which is required as the node HTTP(S) libraries don't support promises out of the box.
Hi i have a weird javascript issue.Here's my code I am not able to send these keys in my designOrder object. My Object does not have these fronImage and backImage keys that i am sending in my code.
let designOrder = await dbCall();
let allImages = []
allImageIds.push(designOrders.frontImageId);
allImageIds.push(designOrders.backImageId);
allImages = await dbCall();
let allImagesHash = {};
allImages.forEach(obj) => {
obj.image = JSON.parse(image)
allImagesHash[image.id] = image;
}
if(designOrder.backImageId){
designOrder.backImage = allImagesHash[designOrder.backImageId]
}
// if i do console.log("1", designOrder.backImage) it will log the designOrder.backImage
if(designOrder.frontImageId){
designOrder.frontImage = allImagesHash[designOrder.frontImageId]
}
// if i do console.log("2", designOrder.frontImage) it will log the designOrder.backImage
// but while console.log("3", designOrder) it will not show the backImage and frontImage keys
return designOrder;
It actually solved it after the first dbCall() i have added this line of code and it worked.
designOrder = designOrder.toJSON();
toJson function is defined within the mongoose schema.
I'm trying to improve a firestore get function, I have something like:
return admin.firestore().collection("submissions").get().then(
async (x) => {
var toRet: any = [];
for (var i = 0; i < 10; i++) {
try {
var hasMedia = x.docs[i].data()['mediaRef'];
if (hasMedia != null) {
var docData = (await x.docs[i].data()) as MediaSubmission;
let submission: MediaSubmission = new MediaSubmission();
submission.author = x.docs[i].data()['author'];
submission.description = x.docs[i].data()['description'];
var mediaRef = await admin.firestore().doc(docData.mediaRef).get();
submission.media = mediaRef.data() as MediaData;
toRet.push(submission);
}
}
catch (e) {
console.log("ERROR GETTIGN MEDIA: " + e);
}
}
return res.status(200).send(toRet);
});
The first get is fine but the performance is worst on the line:
var mediaRef = await admin.firestore().doc(docData.mediaRef).get();
I think this is because the call is not batched.
Would it be possible to do a batch get on an array of mediaRefs to improve performance?
Essentially I have a collection of documents which have foreign references stored by a string pointing to the path in a separate collection and getting those references has been proven to be slow.
What about this? I did some refactoring to use more await/async code, hopefully my comments are helpful.
The main idea is to use Promise.all and await all the mediaRefs retrieval
async function test(req, res) {
// get all docs
const { docs } = await admin
.firestore()
.collection('submissions')
.get();
// get data property only of docs with mediaRef
const datas = await Promise.all(
docs.map(doc => doc.data()).filter(data => data.mediaRef),
);
// get all media in one batch - this is the important change
const mediaRefs = await Promise.all(
datas.map(({ mediaRef }) =>
admin
.firestore()
.doc(mediaRef)
.get(),
),
);
// create return object
const toRet = datas.map((data: MediaSubmission, i) => {
const submission = new MediaSubmission();
submission.author = data.author;
submission.description = data.description;
submission.media = mediaRefs[i].data() as MediaData;
return submission;
});
return res.status(200).send(toRet);
}
I need to create a new array from iterating mongodb result. This is my code.
const result = await this.collection.find({
referenceIds: {
$in: [referenceId]
}
});
var profiles = [];
result.forEach(row => {
var profile = new HorseProfileModel(row);
profiles.push(profile);
console.log(profiles); //1st log
});
console.log(profiles); //2nd log
I can see update of profiles array in 1st log. But 2nd log print only empty array.
Why i couldn't push item to array?
Update
I think this is not related to promises. HorseProfileModel class is simply format the code.
const uuid = require("uuid");
class HorseProfileModel {
constructor(json, referenceId) {
this.id = json.id || uuid.v4();
this.referenceIds = json.referenceIds || [referenceId];
this.name = json.name;
this.nickName = json.nickName;
this.gender = json.gender;
this.yearOfBirth = json.yearOfBirth;
this.relations = json.relations;
this.location = json.location;
this.profilePicture = json.profilePicture;
this.horseCategory = json.horseCategory;
this.followers = json.followers || [];
}
}
module.exports = HorseProfileModel;
await this.collection.find(...)
that returns an array of the found data right? Nope, that would be to easy. find immeadiately returns a Cursor. Calling forEach onto that does not call the sync Array.forEach but rather Cursor.forEach which is async and weve got a race problem. The solution would be promisifying the cursor to its result:
const result = await this.collection.find(...).toArray();
Reference