new here so apologies if I don't lay this out as you'd expect.
So I'm submitting my reactive form data to the server (mongodb database). I then want to route to a new path passing the ID element that the database returns to the front end as a param in the URL.
This is what I have in the submit function so far:
onsubmit(){
let opdata = null;
this.location.saveOpnote(this.form.value)
.subscribe(response => {
opdata = response
console.log(response)
})
this.route.navigate(['/opnotes/mopsdisplay', opdata._id])
}
So data saves perfectly and backend returns the _id of the new entry. Browser complains:
ERROR TypeError: Cannot read property '_id' of null
My understanding is the browser is looking at this before the asynchronous part of saving to the server is completed and the _id is available.
How do I get round this?
Many thanks.
You want your request to be completed, therefore navigation part should be the last line inside the subscription not outside of it. As your call on save is asynchronous as you mentioned, navigation block gets executed before the save operation finishes.
You can create a new function navigateToMopsDisplay just to navigate to your desired route. Once the Opnotes is saved, the opdata response can be sent to navigateToMopsDisplay with opdata._id and can be navigated
navigateToMopsDisplay(id) {
this.route.navigate(["/opnotes/mopsdisplay", id]);
}
onsubmit() {
this.location.saveOpnote(this.form.value).subscribe(response => {
const opdata = response;
this.navigateToMopsDisplay(opdata._id);
});
}
Related
I have created a method in VueJS that fetches data from an API and can accept different parameters that will make different API requests that retrieve different information.
this is the base method and its parameters:
getContents(url, requestType, collection, param = null)
However inside this method, there is a call to another method that will do the actual API fetch.
The thing is that no matter what the API Call is, the fetched contents will always be saved to the same hardcoded variable (in this case the variable this.contents ):
async goGetIt(url) {
try {
let res = await fetch(url);
this.contents = await res.json(); //in this line you should put your destination array where data will be stored.
} catch (error) {
console.log("The request returned the following error: " + error);
}
}
What I would like to implement is for me to be able to pass a pre-created array that would be passed as argument in this function: getContents(url, requestType, collection, param = null, **destinationArray**) and that would then be used as destination for the fetched data.. This would allow me to have several different API Calls Happening at the same time in the same View or Component and saving information to different arrays. Because if I do not implement it, everytime I have 2 different calls of the same method, all the info from the previous fetch will be replaced with the late method call's info.
Is this possible to do with javascript and VueJS?
thank you for your help.
I am currently using a ReactJs frontend with the Firebase Javascript SDK. It is hooked up to a firebase-functions storage emulator using NodeJS in the backend.
Usually, I am able to call a functions.https.onCall(...) cloud function (that has been set up with nodejs) from my frontend and receive a promise, and then I can use the data in the front end normally.
However, using functions.storage.object().onFinalize(...) in the backend, I am trying to force some sort of way to return a success message to my front end after a file has successfully been processed.
Here is what I've tried:
My backend code (Nodejs):
exports.processMedia = functions.storage.object().onFinalize(async (object) =>{
// Here I successfully process any uploaded images
// Issue - After the media has been processed, I'd like to return a message that can be used to update the UI. I've tried to return a new promise like so:
return new Promise((resolve, reject) =>{
return resolve("Success");
});
})
And then in my React UI, I am trying to capture the return message from the backend using a httpsCallable('processMedia') function because I don't know how else to try to get the response.
async processMedia(){
const processMediaCallable = this.functions.httpsCallable('processMedia');
return processMediaCallable;
}
Then I try to log out the values from the promise:
async function getProcessedMessage(){
await firebase.processMedia().then((val) => {
console.log(val);
});
}
I get this output in the browser console for val after I've uploaded a file in the UI and processMedia() in the backend has completed:
ƒ (data) {
return _this.call(name, data, options || {});
}
I am trying to output a success message here. Any thoughts would be greatly appreciated. Thank you.
You cannot return a response to client from a background function. When a user uploads any file to your Firebase storage they get a success response and the function triggered from that event has nothing to do with client. There's a workaround for using Firebase Realtime Database which you can use to emit the response to user.
To break it down in simple steps:
Upload file to Firebase Storage
Create a realtime database listener on client side
After all processing in your Cloud Function, write something in the database and that'll be delivered to your user.
Client:
async function uploadFile() {
// upload to firebase storage
const alertRef = firebase.database().ref(`alerts/${userID}`);
alertRef.on('child_added', (snapshot) => {
const data = snapshot.val();
// Alert received from cloud function
// Delete this alert from database
snapshot.ref.set(null)
});
}
Cloud function:
exports.processMedia = functions.storage.object().onFinalize(async (object) => {
// Process the file
// Add alert in realtime database
const alertRef = firebase.database().ref(`alerts/${userID}`).push()
return alertRef.set({...}) // add any data you would like to pass to client side
})
child_added event is triggered once for each existing child and then again every time a new child is added to the specified path. The listener is passed a snapshot containing the new child's data.
That being said just make sure you are not alerting users multiple times with same notification.
I have a database that holds a table of a list of users (and their respective usernames and passwords). I have a login system that runs a function that returns false when the user is not found and the username/password when it is found. That is then used in the login system but that's irrelevant.
My problem is that that function has to send a query to the database. But the callback actually can't return anything and so I can't just use
await database.query('query things', data = await function(err, res) {function things});
I tried declaring a variable and then inside the query callback setting that variable to the fetched data, and then outside of that query the await holds the rest of the code back, but it just returns undefined. The await does not do anything because of the multiple promise resolves (I think). So what ends up happening is the function returns undefined and the server crashes.
Is there a way that I can pass the fetched data through the function and back to the login system?
Structure:
login calls fetch function; fetch function queries database; callback sets a passthrough; fetch function receives that passthrough and parses it and returns things to the login.
Thank you for being helpful, internet. Unlike last time.
It turns out that because there is a callback inside it does not return a promise so async/await is not useable. I still wanted to not have the server instantly crash when an error occurred but try/catch works fine.
As the title says, i have a part of my react app that tries to get some data from my database, making a select based on the value I passed to it. So im gonna go ahead and first show the code where i think the problem lies:
So first, this is the function from one of my forms that sends the request to the server, i know code is probably ugly, but i can tell from the console.logs that the parameters im sending are what i intend to send(a string called "licenciaInput"
async handleClickLicencia (event) {
event.preventDefault();
console.log(this.state);
console.log("licenciaInput: "+this.state.licenciaInput);
const datoBuscar = this.state.licenciaInput;
axios.get('http://localhost:3001/atletas/:licencia',this.state)
.then(response =>{
console.log(response)
})
.catch(error =>{
console.log(error)
})
And then, i have this function which is called in that localhost route which attempts to get "licencia", and launch a select in my postgresql db where licencia="whatever", you can see the sentence in the code:
const getAtletasByLicencia = (request, response) => {
const licencia = request.body.licenciaInput;
console.log("Request: "+request);
console.log("what the server gets: "+licencia);
// const licencia = request.licenciaInput;
const sentencia ="SELECT * FROM atleta WHERE licencia ='"+licencia+"'";
pool.query(sentencia, (error, results) =>{
if(error){
throw error
}
response.status(200).json(results.rows)
})
}
As you can see, i have console.logs everywhere, and i still cannot access whatever element i send, because i always get on the server console "undefined" value.
TLDR:How can i access the "licenciaInput" i passed from my client form to my server, i have tried request.body.licenciaInput, request.params.licenciaInput, and request.licenciaInput, but none of those seem to work
I also know i have to treat after that the data i receive from the server, but i need to solve this before looking two steps ahead. Im also really new to React and node/express, so feel free to burn me with good practices im not meeting.Thanks in advance
EDIT: Im also adding this code that i have which shows the route for my method in the server:
app.get('/atletas/:licencia', db.getAtletasByLicencia)
As #Gillespie59 suggested that i should send a POST request, but i dont think i should if im both trying to send a parameter to the server to make a select, and then send the results back to the client
Change your request to:
axios.get(`http://localhost:3001/atletas/${this.state.licenciaInput}`)
...
and your route (if you are using express) should look like this:
app.get('/atletas/:licencia', function (req, res) {
var licencia = req.params.licencia
...
})
As you are using request.body you should send a POST request with axios and add a body.
Right, so I'm simply trying to update my object via the REST API. My request succeeds, I get a 200 response back containing the latest updated timestamp, but the object's column value has not changed.
My Movies class has a title and a genre column, the rights on the class are set to public read write on all rows.
Here is some code
var data = {title:'The Revenant'};
qwest.put('https://api.parse.com/1/classes/Movies/myObjectId', JSON.stringify(data))
.then(function(xhr, response) {
console.log(response);
})
.catch(function(xhr, response, e) {
console.log(e);
});
The response I get back?
{"updatedAt":"2016-01-24T07:59:54.977Z"}
So the request succeeded but if I GET the object again or check in the Parse admin page, the object has not changed. What gives?
EDIT
FYI, if I use the Javascript SDK, I can update the model.
var Movies = Parse.Object.extend("Movies");
var query = new Parse.Query(Movies);
query.get(myObjectId, {
success: function (movie) {
movie.set("title", data.title);
movie.save();
},
error: function (object, error) {
console.log(error);
}
});
This updates the model. For my particular use case though, I would really prefer to use the REST API rather than the SDK, but I guess this means it is not a permissions issue or an id mismatch etc.,
code snippet
qwest.put('https://api.parse.com/1/classes/Movies/Dh7zjiP9KW', data, {dataType:"json",headers:{'x-parse-application-id':'XXX','X-Parse-REST- API-Key':'XXX'}})
.then(function(xhr, response) {
console.log(response);
})
.catch(function(xhr, response, e) {
console.log(e);
});
The response you're getting indicates that the object was updated successfully. Double check that you're looking at the correct object, and that the "updatedAt" field matches the response you saw earlier.
What happens if you fetch the object right away, using the same "qwest" client and https://api.parse.com/1/classes/Movies/myObjectId resource URL (with the correct object id)?
Try removing JSON.stringify(data) and just pass data,