How to modify an object after axios get request is resolved - javascript

I am setting the res.data of an object containerInfo in Vue afer making an axios get request, like so:
methods: {
searchContainers(containerSearch) {
this.containerQuery = JSON.parse(containerSearch.container_query)[0];
this.imageBranch = JSON.parse(containerSearch.container_query)[1];
this.containerInfo["image_branch"] = this.imageBranch
this.url = this.containerQuery.split('/');
axios.get(`http://localhost:8000/get?name=${this.url[0]}/${this.url[1]}/${this.url[2]}&ver=${this.url[3]}`)
.then(res => this.containerInfo = res.data)
.then(this.containerInfo = [...this.containerInfo, this.imageBranch]);
}
I want to add this.imageBranch to the containerInfo object after the data object is received/set in vue.
The issue is that the axios res, once received (takes a few secs), deletes the this.imageBranch key/value added. I know I should probably add it after the promise is resolved but I can't figure out how.
Can someone please help!

Instead of using two .then, use only one and execute all your code inside the arrow function, like this:
methods: {
searchContainers(containerSearch) {
this.containerQuery = JSON.parse(containerSearch.container_query)[0];
this.imageBranch = JSON.parse(containerSearch.container_query)[1];
this.containerInfo["image_branch"] = this.imageBranch
this.url = this.containerQuery.split('/');
axios.get(`http://localhost:8000/get?name=${this.url[0]}/${this.url[1]}/${this.url[2]}&ver=${this.url[3]}`)
.then(res => {
this.containerInfo = res.data;
this.containerInfo = [...this.containerInfo, this.imageBranch]
});
}

I recommend using await/async syntax which is clear and straightforward. So the codes should be like this
async searchContainers() {
const res = await axios.get(`http://localhost:8000/get?name=${this.url[0]}/${this.url[1]}/${this.url[2]}&ver=${this.url[3]}`);
this.containerInfo = res.data;
this.containerInfo = [...this.containerInfo, this.imageBranch];
}

I figured it out. Needed to set a key in object as such: this.containerInfo.image_branch = this.imageBranch

Related

using multiple api calls, after first api others return undefined

Everyone does a weather app for api practice so I decided to do something different I'm using Pokeapi to make a small app. I have to call a few different apis to make it work how I want which is being done like this
const api = "https://pokeapi.co/api/v2/pokemon";
const apiMoves = "https://pokeapi.co/api/v2/move";
const apiSpecies = "https://pokeapi.co/api/v2/pokemon-species"
const searchBox = document.querySelector(".search-box");
searchBox.addEventListener("keypress", setQuery);
function setQuery(e) {
if (e.keyCode == 13) {
getResults(searchBox.value);
searchBox.value = "";
}
}
function getResults(query) {
const pokemonData = fetch(`${api}/${query}`)
.then((data) => {
return data.json();
});
pokemonData.then(displayResults)
pokemonData.then(data => {
return fetch(`${apiMoves}/${data.moves[0].move.name}`)
.then(data => data.json())
.then(move => {
console.log(move)
})
})
pokemonData.then(data => {
return fetch(`${apiSpecies}/${query}`)
.then(data => data.json())
.then(species => {
console.log(species)
})
})
}
all 3 of the end points are being logged in the console so I can see them. However looking at api call 2 I'm passing info from the first api call to get more info and that logs fine. When I'm trying to display the info from that 2nd api call it just returns undefined but in the console I can see all the endpoints.
the display results looks something like this.
function displayResults(pokemon) {
let name = document.querySelector('h2')
name.innerText = pokemon.name <-- this works.
let dmg1 = document.querySelector('.dmg1')
dmg1.innerText = pokemon.power <-- this is returning undefined but in the console "power" shows a number.
}
I've tried to replace the pokemon.power with move.power but that gives an error saying "move" is not defined.
I'm thinking that I'm simply calling the 2nd and 3rd api wrong? I'm not sure and trying to search for this issue is a bit rough.
any help is appreciated!
const pokeApiPrefix = 'https://pokeapi.co/api/v2/';
const apiPokemon = `${pokeApiPrefix}pokemon`;
const apiMoves = `${pokeApiPrefix}move`;
const apiSpecies = `${pokeApiPrefix}pokemon-species`;
const searchBox = document.querySelector('.search-box');
searchBox.addEventListener('keypress', setQuery);
function setQuery(e) {
if (e.keyCode == 13) {
getResults(searchBox.value.toLowerCase());
searchBox.value = '';
}
}
getResults('Dragonite'.toLowerCase());
function getResults(pokemon) {
let dmg1 = document.querySelector('.dmg1');
dmg1.innerText = `Getting results. Please wait...`;
const pokemonData = fetch(`${apiPokemon}/${pokemon}`)
.then((data) => data.json())
.then((data) => {
console.log(`pokemon data:`, data);
displayPokemonName(data);
const moveName = data.moves[0].move.name;
return fetch(`${apiMoves}/${moveName}`);
})
.then((data) => {
return data.json();
})
.then((data) => {
displayMovePower(data);
console.log(`move data:`, data);
return fetch(`${apiSpecies}/${pokemon}`);
})
.then((data) => data.json())
.then((data) => {
console.log(`species data:`, data);
});
}
// function displayResults(pokemon) {
// let name = document.querySelector('h2');
// name.innerText = pokemon.name;
// let dmg1 = document.querySelector('.dmg1');
// // I couldn't find 'power' attribute on api results, used id instead
// // https://pokeapi.co/docs/v2#pokemon
// dmg1.innerText = `#${pokemon.id}`;
// }
function displayPokemonName(pokemon) {
let name = document.querySelector('h2');
name.innerText = `Pokemon name: ${pokemon.name}`;
}
function displayMovePower(move) {
let dmg1 = document.querySelector('.dmg1');
dmg1.innerText = `Move power: ${move.id}`;
}
<input type="text" class="search-box" />
<h2></h2>
<div class="dmg1"></div>
I've created a snippet, chaining multiple promises and logging every result on the console.
As stated, it seems you are trying to use an attribute 'power', which is not present in the first pokemon api call
Here this line is not working because you are trying to access the attribute which does not exist in the object.
let dmg1 = document.querySelector('.dmg1')
dmg1.innerText = pokemon.power <-- this is returning undefined but in the console "power" shows a number.
What might work for you is:
dmg1.innerText = pokemon.moves[0].move.name

What function is passed to cb here?

So I have a small project containing both frontend (html) and backend (express: server, routers) parts. The project isn't that clean, so the its main operationality is launched directly in html section. And not much is clear to me here, especially what function is passed to cb (callback) here?
I have the following code in part of my html page within js project:
const $ = document.getElementById.bind(document)
const request = (path, cb) =>
fetch(path)
.then((res) => {
if (res.ok) return res.json()
throw Error('HTTP error: ' + res.status)
})
.then(cb)
.catch((err) => ($('result').innerHTML = err))
const main = async () => {
const pinRequired = new URLSearchParams(document.location.search).get('pin')
const id = await request(`./qrcode?pin=${pinRequired}`, (json) => {
const { qrbase64, deeplink, pin, id } = json
$('qrcode').innerHTML = `<img src="${qrbase64}" alt="Red dot" />`
$('deeplink').innerHTML = ` ${deeplink.slice(0, 90)}...`
$('pin').innerHTML = pin ? pin : 'Not requested'
return id
})
setInterval(() => request(`./status?id=${id}`, ({ status }) => ($('result').innerHTML = status)), 1000)
}
main().catch(console.log)
Is this (json)? I also don't know why it is in () round brackets, however, it is an object, it cannot be passed as a callback, right?
And I also have a code in another file, which contains /qrcode route of my website. There is a function (quite big, so i'm not posting it, just pointing that it doesn't return function that may be passed as a callback).
If this callback 100% is in another part of the code, as you think, please let me know.
If what you're asking about is this callback (json) => { ... } in the code below:
request(`./qrcode?pin=${pinRequired}`, (json) => {
const { qrbase64, deeplink, pin, id } = json
$('qrcode').innerHTML = `<img src="${qrbase64}" alt="Red dot" />`
$('deeplink').innerHTML = ` ${deeplink.slice(0, 90)}...`
$('pin').innerHTML = pin ? pin : 'Not requested'
return id
});
Then this is what is known as an arrow function. You can read about them here on MDN. They are a shortcut syntax for declaring a function that also has a number of implementation differences.
Note, there are some other issues in your code as request() does not return a promise so it does no good to use await on it and you won't get the id back from return id either.
Also note that the request library has been deprecated and generally shouldn't be used for new code. There is a list of alternatives here, all of which support promises natively. My favorite in that list is the got() library.

How can I make a POST request in react native

So I created a website where I used JS and jQuery to send data to a server.
But now I am making that website as an app on my phone using react native.
I've read about the fetch function but I don't completely understand how I would go about it to make this request.
This is the code I used on my website:
$(".btn").click(function() {
var p = $(this).attr('id');
pin: p
$.get("http://192.168.0.129:80/", {
pin: p
});
DisableButtons();
});
Right now I have the following:
sendData = (data) => {
console.log(data);
var p = data;
pin: p
$.get("http://192.168.0.129:80/", { --> this needs to be changed so it could work
pin: p in react native
});
}
So what I want to accomplish is to send this url when I call the function: http://192.168.0.129/?pin=xxx
Thanks in advance
A typical fetch request in javascript looks like this.
const sendData = async(data) => {
const response = await fetch(`http://192.168.0.129:80/?pin=${p}`).then(res => res.json()) //or res.text() if you are expecting text response.
console.log('results')
}
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
So I got the solution, it was simpler then I thought:
sendData = (data) => {
console.log(data);
var url = `http://192.168.0.129:80/?pin=${data}`;
fetch(url);
}

Navigating JSON tree to data from Reddit API

I will try and keep this short. I am a current student and have been attempting to retrieve the top 5 posts from the front page of Reddit and display the title and URL on an HTML page. It is probably something really simple, but I can't get it to work. I want to pass the data to my Handlebars template from a single variable. I keep receiving an unhandled promise warning. Here is my code.
let url = 'https://www.reddit.com/.json?limit=5';
let settings = { method: "Get"};
let redditData = ""
fetch(url, settings)
.then(res => res.json())
.then(data => {
redditData = [
{
title: data.children.data.title,
url: data.children.data.url_overriden_by_dest
}
];
});
The data object is structured differently than they way you've coded it. Here is how to extract the information you want from the first child:
let url = 'https://www.reddit.com/.json?limit=5';
let settings = { method: "Get"};
let redditData = ""
fetch(url, settings)
.then(res => res.json())
.then(data => {
redditData = [
{
title: data.data.children[0].data.title,
url: data.data.children[0].data.url_overriden_by_dest
}
];
});
You might want to check some documentation on how the function fetch works here.
Also, check how promises work here.
That being said, you have to access the object properties, only when the Promise has finished retrieving the data. One way is using the Promise.allSettled function.
Please see the following snippet working, with a slightly different way of organizing it:
const url = "https://www.reddit.com/.json?limit=5";
const promise = fetch(url).then(res => res.json());
function formatHandlebarsData(data) {
const childrenObj = data.value.data.children;
return childrenObj.map(element => ({
title: element.data.title,
url: element.data.url
}));
}
Promise.allSettled([promise]).then(([data]) => {
const handlebarsData = formatHandlebarsData(data);
// You can use the object now
console.log(handlebarsData);
});
Awesome. I was able to get it working with
let url = 'https://www.reddit.com/.json?limit=5';
let settings = { method: "Get"};
let redditData = ""
fetch(url, settings)
.then(res => res.json())
.then(data => {
redditData = [
{
title: data.data.children[0].data.title,
url: data.data.children[0].data.url_overriden_by_dest
}
];
});
Thanks!

JavaScript Google Cloud Function: write Stripe values to Firebase

I'm new to JavaScript and I have written the following JS Google Cloud Function with the help of various resources.
This function handles a Stripe invoice.payment_succeeded event and instead of writing the entire data I am trying to save just both the sent period_start and period_end values back to the correct location in my Firebase DB (see structure below).
How can I write these two values in the same function call?
exports.reocurringPaymentWebhook = functions.https.onRequest((req, res) => {
const hook = req.body.type;
const data = req.body.data.object;
const status = req.body.data.object.status;
const customer = req.body.data.object.customer;
const period_start = req.body.data.object.period_start;
const period_end = req.body.data.object.period_end;
console.log('customer', customer);
console.log('hook:', hook);
console.log('status', status);
console.log('data:', data);
console.log('period_start:', period_start);
console.log('period_end:', period_end);
return admin.database().ref(`/stripe_ids/${customer}`).once('value').then(snapshot => snapshot.val()).then((userId) => {
const ref = admin.database().ref(`/stripe_customers/${userId}/subscription/response`)
return ref.set(data);
})
.then(() => res.status(200).send(`(200 OK) - successfully handled ${hook}`))
.catch((error) => {
// We want to capture errors and render them in a user-friendly way, while
// still logging an exception with StackDriver
return snap.ref.child('error').set(userFacingMessage(error));
})
.then((error) => {
return reportError(error, {user: context.params.userId});
});
});//End
HTTP type functions are terminated immediately after the response is sent. In your code, you're sending the response, then attempting to do more work after that. You will have to do all the work before the response is sent, otherwise it may get cut off.
If you just want to save the period_start and period_end values, instead of the entire data object, you can use the update() method (see https://firebase.google.com/docs/database/web/read-and-write#update_specific_fields).
You should then modify your code as follows. (Just note that it is not clear from where you receive the userId value, since you don't show the stripe_ids database node in your question. I make the assumption that it is the value at /stripe_ids/${customer}. You may adapt that.)
exports.reocurringPaymentWebhook = functions.https.onRequest((req, res) => {
const hook = req.body.type;
const data = req.body.data.object;
const status = req.body.data.object.status;
const customer = req.body.data.object.customer;
const period_start = req.body.data.object.period_start;
const period_end = req.body.data.object.period_end;
admin.database().ref(`/stripe_ids/${customer}`).once('value')
.then(snapshot => {
const userId = snapshot.val();
let updates = {};
updates[`/stripe_customers/${userId}/subscription/response/period_start`] = period_start;
updates[`/stripe_customers/${userId}/subscription/response/period_end`] = period_end;
return admin.database().ref().update(updates);
})
.then(() => res.status(200).send(`(200 OK) - successfully handled ${hook}`))
.catch((error) => {...});
});

Categories

Resources