API Integration - How to extract only values from Object Array using JS? - javascript

Need assistance with Javascript - API Integration. I have been trying to pull data off SWAPI (an open API) and fetch the data into our system. I am struggling with something now!
What I am trying to do is get the around 3 country names and get the people's attribute under that country. So fat I was able to get the country names using the following code:
(async () => {
let Name = [];
let Diameter = [];
let Resident = [];
for (i = 1; i < 4; i++) {
const PlanetDetails = await api.makeRequest({
method: 'GET',
url: `https://swapi.dev/api/planets/${[i]}`,
});
Name[i] = PlanetDetails.data.name;
Resident[i] = PlanetDetails.data.residents;
api.setVariable('Name1', Name[1]);
api.setVariable('Name2', Name[2]);
api.setVariable('Name3', Name[3]);
api.setVariable('R1', Resident[1]);
}
})();
But under the countries the residents' attributes are coming up as links like this:
I used POSTMAN here to test. When I click on the links I can see the person's attributes (e.g color, height, name, etc.). But How do I do that in JS?
Thank you

To get the resident's data, you need to make a request to the endpoint and then use the returned data. for example to get the data of the first resident, you can make a request to https://swapi.dev/api/people/1.
This code makes requests for each resident.
(async () => {
let Name = [];
let Diameter = [];
let Resident = [];
for (i = 1; i < 4; i++) {
const PlanetDetails = await api.makeRequest({
method: 'GET',
url: `https://swapi.dev/api/planets/${[i]}`,
});
Name[i] = PlanetDetails.data.name;
Resident[i] = await Promise.all(PlanetDetails.data.residents.map(async(resident) => {
let resident = await api.makeRequest({
method: 'GET',
url: resident,
});
console.log(resident.data); // for visually viewing the result.
return resident.data;
}));
api.setVariable('Name1', Name[1]);
api.setVariable('Name2', Name[2]);
api.setVariable('Name3', Name[3]);
api.setVariable('R1', Resident[1]);
}
})();

Related

How do i execute fetch() before other funcitons?

I'm currently learning JavaScript, and has been playing around with API's (Yahoo Finance in this example).
The goal is to update a table of values with a specific stock's financial data - but I need to fetch the data, before it updates the data. Thought I could use await/async as shown, but it doesn't work.
Any pointers?
let stats;
let inputSymbol;
let stockName;
let stockSymbol;
let stockPrevClose;
let stockOpen;
let stockMarketCap;
let stockDayHigh;
function getStockStatistics(){
//Get symbol from input field
inputSymbol = document.getElementById("inputSymbol").value;
console.log(inputSymbol);
request();
updateStockTabel();
}
//Fetch data from Yahoo Finance API based on variables
const request = async () => {
const response = await fetch(`https://apidojo-yahoo-finance-v1.p.rapidapi.com/stock/v2/get-financials?symbol=${inputSymbol}&region=US`, {
"method": "GET",
"headers": {
"x-rapidapi-key": "---",
"x-rapidapi-host": "---"
}
});
const data = await response.json();
stats = data;
console.log(data);
}
//Update statistics in table based on values from Yahoo Finance JSON object
function updateStockTabel() {
//Change properties
stockPrevClose = stats.summaryDetail.previousClose.raw;
stockOpen = stats.summaryDetail.open.raw;
stockMarketCap = stats.summaryDetail.marketCap.fmt;
stockDayHigh = stats.price.regularMarketDayHigh.fmt;
stockName = stats.price.longName;
stockSymbol = stats.meta.symbol;
//Connect document properties with variables
document.getElementById("stocPrevClose").innerText = stockPrevClose;
document.getElementById("stockOpen").innerText = stockOpen
document.getElementById("stockMarketCap").innerText = stockMarketCap;
document.getElementById("dayHigh").innerText = stockDayHigh;
document.getElementById("stockName").innerText = stockName;
document.getElementById("stockSymbolOutput").innerText = stockSymbol;
}
You have 2 options mainly: leave your code exactly as it is now, but use this to wait to run updateStockTabel :
request().then(() => updateStockTabel());
OR change your getStockStatistics to an async function to do something pretty similar, but with async/await syntax:
async function getStockStatistics(){
//Get symbol from input field
inputSymbol = document.getElementById("inputSymbol").value;
console.log(inputSymbol);
await request();
updateStockTabel();
}

Dynamically creating multidimensional inline keyboard telegram bot api?

My Code:
var keyBoardData = [];
var menu = ['Nightclub', 'Parks'];
for (var i = 0; i < menu.length; i++) {
keyBoardData.push([{'text': menu[i], 'callback_data': '{"a":(menu[i]),"b":(menu[i])}' }]);
}
var keyBoard = {"inline_keyboard": keyBoardData};
result is:
{"inline_keyboard":[[{"text":"Nightclub","callback_data":"{\"a\":(menu[i]),\"b\":(menu[i])}"}],
[{"text":"Parks","callback_data":"{\"a\":(menu[i]),\"b\":(menu[i])}"}]]}
but am trying to get:
{"inline_keyboard":[[{"text":"Nightclub","callback_data":'{"a":"Nightclub","b":"Nightclub"}'}],
[{"text":"Parks","callback_data":'{"a":"Parks","b":"Parks"}'}]]}
working with telegram bot api and google sheets app script.
need to display a column data as Buttons in telegram and on selection of button needs to filter sheets data using callback_data and return the result.
am having issue here: '{"a":(menu[i]),"b":(menu[i])}' this fits inline keyboard but menu[i]) treating as text.
if i remove single quotes am able to get data but inline keyboard not works.
any suggestion.
Don't create json by hard-coding strings.
Use JSON.stringify() and URLSearchParams() to format the required data;
An example, using the same data; with the result below;
// Create keyBoard data
var keyBoardData = [];
var menu = ['Nightclub', 'Parks'];
for (var i = 0; i < menu.length; i++) {
keyBoardData.push({
text: menu[i],
callback_data: menu[i]
});
}
// Create fetch options
var requestOptions = new URLSearchParams({
reply_markup: JSON.stringify({ "inline_keyboard": [ keyBoardData ]}),
chat_id: 12345678,
text: 'Test Keyboard'
}).toString();
// Send test
const token = '1134534202?????????????';
fetch("https://api.telegram.org/bot" + token + "/sendMessage?" + requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));

Routing function not being called

I am working on a simple restaurant web app which uses a mongo-db database to store the menu items. My issue is that I have a client js file that will use a routing function that then accesses the database to return all the menu items of a certain restaurant. My issue is that my endpoint for the url isn't being recognized:
Client.js
function readMenu(rest){
(async () => {
// const newURL = url + "/menus/"+rest
const resp = await fetch(url+"/menus/"+rest)
const j = await resp.json();
itemlist = j["items"]
var element = document.getElementById("menu")
var i;
for (i = 0; i < itemlist.length; i++) {
var para = document.createElement("p")
item = itemList[i]
text = item["name"]+" | "+item["cost"]+" | "+item["descr"] +"<br>";
var node = document.createTextNode(text)
para.appendChild(node)
element.appendChild(para)
}
})
}
Server-routing.ts (Routings):
this.router.get("/menus", this.getResturants.bind(this))
this.router.post("/menus", this.addResturaunt.bind(this))
this.router.get("/menus/:rest", this.getResturauntItems.bind(this))
this.router.delete("/menus/:rest",this.deleteResturaunt.bind(this))
this.router.get("/menus/:rest/:item",[this.errorHandler.bind(this),this.getItem.bind(this)])
this.router.post("/menus/:rest",this.addItem.bind(this))
this.router.delete("/menus/:rest/:item",this.deleteItem.bind(this))
Server-routing.ts (function):
public async getResturauntItems(request, response) : Promise<void> {
console.log("Getting Restaurant Items")
let rest = request.params.rest
let obj = await this.theDatabase.getResturauntItems(rest)
console.log(obj)
response.status(201).send(JSON.stringify(obj))
response.end()
}
So, what should happen is a button calls readMenu(), it then makes a GET fetch request to localhost:8080/api/menus/ and then the menu items from the collection should be returned. The issue is that when I click the button, nothing happens. I know it is not being redirected to some other function as they all have "console.log()" to keep track of them and none of them where called. I used the "inspect" tool to see if the request was being sent or received anywhere and nothing. I am unsure of what the issue happens to be. If anyone can help, it would be really appreciated.
you just never called your function, you declared the async function inside your function but never called it.
function readMenu(rest){
(async () => {
// const newURL = url + "/menus/"+rest
const resp = await fetch(url+"/menus/"+rest)
const j = await resp.json();
itemlist = j["items"]
var element = document.getElementById("menu")
var i;
for (i = 0; i < itemlist.length; i++) {
var para = document.createElement("p")
item = itemList[i]
text = item["name"]+" | "+item["cost"]+" | "+item["descr"] +"<br>";
var node = document.createTextNode(text)
para.appendChild(node)
element.appendChild(para)
}
})();
}
you need to add () after creating the functions to call it.

Vue.js combine data from RESP API

I need combine multple API calls on a final object, this because API have limits to be consumed, any have an idea how is possible combine multiple calls in same final object, next is an example of my code, I need all data in this.lista but is not working:
created(){
this.$http.get('/api/transactions?senderId=8642612272713533685S&limit=1&offset=000')
.then( function(res){
console.log(res.body.count);
let limit = Math.ceil(res.body.count/1000);
console.log(limit);
let m = {};
let off = 0;
for (var i = 0; i <= limit; i++) {
this.$http.get('/api/transactions?senderId=8642612272713533685S&limit=1000', {params:{offset: off}})
.then( function(data){
this.lista = { ...this.lista, ...data.body.transactions }
} )
off = off + 1000;
}
}
);
}
any help will be appreciated
Using Promise.all is most likely what you are looking for. I will write just enough code for you to understand where to go.
// Populate your array array with URLs you want to get
let urls = ["url1", "url2", "...and so on"];
// Make into web request promises
let httpReqPromises = urls.map( url => this.$http.get(url) )
// Wait for all of them to resolve
Promise.all(httpReqPromises).then(allResponses => {
// Put them all together
this.lista = allResponses.reduce((a, b) => ({...a, ...b}, {})
})
The only work I leave up to you is how you populate the url variable.

NodeJS + TinyURL - adding items to a list

Sorry if this is a stupid question, but how would I go about adding items into a list? So what I've got is a loop that basically runs through and tries to convert all the urls to tinyurls from a web scraper . It still produces an empty list for images_short. I'm not very familiar with nodejs's syntax. Here's a snippet of code, I've put some data in the images_long list:
const TinyURL = require('tinyurl');
var images_long = ['https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d', 'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
var images_short = [];
for (i = 0; i < 2; i++) {
TinyURL.shorten(images_long[i], function(res) {
images_short.push(res[i]);
});
}
I still get an empty list when I changed images_short.push(res[i]); to images_short.push(res);
res is a string, so just images_short.push(res); will do the trick. Also, you should iterate with respect to the length of the variable you're indexing, and you should var your indexing variable (i):
const TinyURL = require('tinyurl');
var images_long = [
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d',
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
var images_short = [];
for (var i = 0; i < images_long.length; i++) {
TinyURL.shorten(images_long[i], function(res) {
images_short.push(res);
});
}
The tinyurl library is async.
Is we use native map, the resulting callback wouldn't be returned if we try to console.log(images_short) until all the links in the array have been shortened.
We can however, use async and specificically use async.map to return the results like the example below.
const TinyURL = require('tinyurl');
const async = require('async');
var images_long = [
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-skateboarding-lucas-premiere-adv-primeknit-khaki-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=728297932403d74d2ac1afa5ecdfa97d',
'https://hypebeast.imgix.net/http%3A%2F%2Fhypebeast.com%2Fimage%2F2017%2F06%2Fadidas-nmd-r1-stlt-triple-black-first-look-0.jpg?fit=max&fm=pjpg&h=344&ixlib=php-1.1.0&q=90&w=516&s=918752eba81826e4398950efc69a5141'];
function shorten(item, cb) {
TinyURL.shorten(item, function(res) {
cb(null, res);
});
}
async.map(images_long, shorten, (err, results) => {
console.log(results);
});
we can assign images_short if you want to keep consistency.

Categories