Vue.js combine data from RESP API - javascript

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.

Related

Adding more elements to an object in javascript

Context: I'm fetching 'car' data below (see the code that starts with "for") from a GET request and am pushing it to the 'array' array. And for each car.ID that I get, I need to run another GET request in sequence (the GET uses car.ID as a parameter and I have no problems in doing this).
Problem: after I fetch the results from the second GET, how to push the data to the same object of the array (i.e. I want to "complement" the object above that ended on car.BrandID by adding a few more key: value pairs to the same "line")?
THANK YOU IN ADVANCE.
for (let car of carsJustObtained) {
for (i=0; i<=2; i++){
array.push(
{
timestamp: epoch,
ID : car.ID,
BrandID : car.BrandID
})
//code continues but don't worry
FULL CODE BELOW:
function gotCars(carsJustObtained) {
for (let car of carsJustObtained) {
for (i=0; i<=2; i++){
array.push(
{
timestamp: epoch,
ID : car.ID,
BrandID : car.BrandID,
ModelID : car.ModelID,
}
);
//given car.ID the second GET will be triggered because the path depends on this variable!
let path_get_all_prices = `xxx=${car.ID}?securityToken=xxx&vehiclePriceTypeID=xxx`;
let get = https.get(
{
hostname: 'xxx.com',
path: path_get_all_prices
},
(getRes) => {
console.log(`getting prices for car ${car.ID}...`);
var reply = "";
getRes.on("data", (chunk) => (reply += chunk));
const obj = JSON.parse(reply);
gotPrices(obj.Response);
}
);
function gotPrices(pricesJustObtained) {
for (let price of pricesJustObtained){
array.push(
//how to add results to the same array of the 1st GET? There are three 'prices' for each car.ID
)};
};
};
You have to find the index of your object in your array, then you can add everything you can to this object :
array[index].name = 'Hello';
There are many ways to do this. I recommend you read about array.map()
This function lets you iterate your array and in each iteration perform the get request and extend the current element.
The key is to recognise that you are not pushing, the second time
What you are doing is reading each element of the array, and adding some information to that element.
for (let car of carsJustObtained) {
const newInfo=getFurtherInformationAboutCar(car) // this is your second getting
car.newInfo1 = newInfo.param1;
car.newInfo2 = newInfo.param2;
car.newInfo3 = newInfo.param3;
}
To answer your specific question about "merging" information
If you have one set of properties already defined for the car, and you want to merge in multiple new properties, a simple way to do it is as follows:
car = { ...car, ...objectContainingNewProperties};
If your original car was {a:2, b:3, c:4} and objectContainingNewProperties was {c: 10, d:20, e:30}, the result would be:
{ a:2,
b:3,
c:10,
d:20,
e:30 }
Any same-named properties in the second object will overwrite those in the original object.
Your second request is of course asynchronous, so by the time you get its response, you have already populated your array with all information from the first request.
I would suggest to use a promise-enabled alternative to http.get, as promises are a native feature in JavaScript that makes working with asynchronous events less messy. I will show here how it can work with node-fetch.
As fetch is natively supported in browser agents, you can run the snippet below to see the result. As a demo I have used https://jsonplaceholder.typicode.com/ as a server resource: it returns JSON for several sample datasets, including todos and users. A todo has some properties (like a title) and has a user id. A user has an email and a username. So we could make the todos-request the first request, and the users-request the second one (based on the user id received in the first). So the principle is the same as with your cars and prices.
This relies heavily on promises:
// For demo, we use these two URls:
// They both need a number following it
let url1 = "https://jsonplaceholder.typicode.com/todos/";
let url2 = "https://jsonplaceholder.typicode.com/users/";
let promises = [];
// Let's say we build an array with 5 objects:
for (let i = 1; i <= 5; i++) {
promises.push(
// Make the request
fetch(url1 + i*30)
// Parse the response as JSON
.then(resp => resp.json())
// Process this data
.then(data => {
// Create our own object from this data
let obj = {
user: data.userId,
todo: data.title
};
// Make second request, to get user's email, joining it with obj
return Promise.all([obj, fetch(url2 + obj.user)])
})
.then(([obj, resp2]) => Promise.all([obj, resp2.json()]))
// Merge the new data with the old
.then(([obj, data2]) => Object.assign(obj, {
email: data2.email,
logon: data2.username
}))
);
}
// Wait for all requests to finish...
Promise.all(promises).then(results => {
console.log(results); // The result!
});
With async/await
The above can be made even more readable, if you use the async/await syntax:
let url1 = "https://jsonplaceholder.typicode.com/todos/";
let url2 = "https://jsonplaceholder.typicode.com/users/";
async function getOne(i) {
let resp = await fetch(url1 + i*30);
let data = await resp.json();
// Create object from first request
let obj = {
user: data.userId,
todo: data.title
};
// Make second request, joining it with obj
let resp2 = await fetch(url2 + obj.user);
let data2 = await resp2.json();
return Object.assign(obj, {
email: data2.email,
logon: data2.username
});
}
let promises = [];
for (let i = 1; i <= 5; i++) {
promises.push(getOne(i));
}
Promise.all(promises).then(results => {
console.log(results);
});

asynchronous loop for in Javascript

I'm trying to iterate and print out in order an array in Javascript that contains the title of 2 events that I obtained from doing web scraping to a website but it prints out in disorder. I know Javascript is asynchronous but I'm new in this world of asynchronism. How can I implement the loop for to print the array in order and give customized info?
agent.add('...') is like console.log('...'). I'm doing a chatbot with DialogFlow and NodeJs 8 but that's not important at this moment. I used console.log() in the return just for debug.
I tried the next:
async function printEvent(event){
agent.add(event)
}
async function runLoop(eventsTitles){
for (let i = 0; i<eventsTitles.length; i++){
aux = await printEvent(eventsTitles[i])
}
}
But i got this error error Unexpected await inside a loop no-await-in-loop
async function showEvents(agent) {
const cheerio = require('cheerio');
const rp = require('request-promise');
const options = {
uri: 'https://www.utb.edu.co/eventos',
transform: function (body) {
return cheerio.load(body);
}
}
return rp(options)
.then($ => {
//** HERE START THE PROBLEM**
var eventsTitles = [] // array of event's titles
agent.add(`This mont we have these events available: \n`)
$('.product-title').each(function (i, elem) {
var event = $(this).text()
eventsTitles.push(event)
})
agent.add(`${eventsTitles}`) // The array prints out in order but if i iterate it, it prints out in disorder.
// *** IMPLEMENT LOOP FOR ***
agent.add(`To obtain more info click on this link https://www.utb.edu.co/eventos`)
return console.log(`Show available events`);
}).catch(err => {
agent.add(`${err}`)
return console.log(err)
})
}
I would like to always print out Event's title #1 and after Event's title #2. Something like this:
events titles.forEach((index,event) => {
agent.add(`${index}. ${event}`) // remember this is like console.log(`${index}. ${event}`)
})
Thanks for any help and explanation!
There no async case here but if you still face difficultly than use this loop
for (let index = 0; index < eventsTitles.length; index++) {
const element = eventsTitles[index];
agent.add(${index}. ${element})
}

Fetching data in the loop

So I'm trying to connect to external server called Pexels to get some photos. I'm doing that from node.js but it is just a javascript issue. Pexels unfortunately lets user to download object with only 40 pictures per page.
https://api.pexels.com/v1/curated?per_page=40&page=1 // 40 is maximum
But actually I need more then that. I'd like to get 160 results, ie. to combine all first four pages. In order to do that I tried looping the request:
let pexelsData = [];
for(let i = 1; i < 5; i++) {
const randomPage = getRandomFromRange(1, 100); //pages should be randomized
const moreData = await axios.get(`https://api.pexels.com/v1/curated?per_page=40&page=${randomPage}`,
createHeaders('bearer ', keys.pexelsKey));
pexelsData = [ ...moreData.data.photos, ...pexelsData ];
}
Now I can use pexelsData but it work very unstable, sometimes it is able to get all combined data, sometimes it crashes. Is there a correct and stable way of looping requests?
You work with 3rd party API, which has rate limits. So you should add rate limits to your code. The simplest solution for you is using p-limit or similar approach form promise-fun
It will looks like that:
const pLimit = require('p-limit');
const limit = pLimit(1);
const input = [
limit(() => fetchSomething('foo')),
limit(() => fetchSomething('bar')),
limit(() => doSomething())
];
(async () => {
// Only one promise is run at once
const result = await Promise.all(input);
console.log(result);
})();
you can break it into functions like..
let images=[];
const getResponse = async i=> {
if(i<5)
return await axios.get(`https://api.pexels.com/v1/curated?per_page=40&page=${i}`)
}
const getImage = (i)=>{
if(i<5){
try {
const request = getResponse(i);
images = [...images,...request];
// here you will get all the images in an array
console.log(images)
getImage(++i)
} catch (error) {
console.log("catch error",error)
// getImage(i)
}
}
}
getImage(0); //call initail

React Axios API call with array loop giving wrong order?

I was learning react and doing some axios api call with an array. I did a code on gathering data through coinmarketcap api to learn.
So, my intention was to get the prices from the api with a hardcoded array of cryptocurrency ids and push them into an array of prices. But I ran into a problem with the prices array, as the prices were all jumbled up. I was supposed to get an array in this order
[bitcoinprice, ethereumprice, stellarprice, rippleprice]
but when I ran it in the browser, the prices came randomly and not in this order, sometimes I got my order, sometimes it didn't. I used a button which onClick called the getPrice method. Does anyone know what went wrong with my code? Thanks!
constructor(){
super();
this.state = {
cryptos:["bitcoin","ethereum","stellar","ripple"],
prices:[]
};
this.getPrice = this.getPrice.bind(this);
}
getPrice(){
const cryptos = this.state.cryptos;
console.log(cryptos);
for (var i = 0; i < cryptos.length; i++){
const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];
axios.get(cryptoUrl)
.then((response) => {
const data = response.data[0];
console.log(data.price_usd);
this.state.prices.push(data.price_usd);
console.log(this.state.prices);
})
.catch((error) => {
console.log(error);
});
}
}
If you want to receive the data in the order of the asynchronous calls you make, you can use Promise.all, that waits until all the promises of an array get executed and are resolved, returning the values in the order they were executed.
const cryptos = ['bitcoin', 'ethereum', 'stellar', 'ripple'];
const arr = [];
for (var i = 0; i < cryptos.length; i++){
const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];
arr.push(axios.get(cryptoUrl));
}
Promise.all(arr).then((response) =>
response.map(res => console.log(res.data[0].name, res.data[0].price_usd))
).catch((err) => console.log(err));
You could use a closure in the for loop to capture the value of i and use it as the index once the data is returned rather than using push:
getPrice(){
const cryptos = this.state.cryptos;
console.log(cryptos);
for (var i = 0; i < cryptos.length; i++) {
const cryptoUrl = 'https://api.coinmarketcap.com/v1/ticker/' + cryptos[i];
(function (x) {
axios.get(cryptoUrl)
.then((response) => {
const data = response.data[0];
console.log(data.price_usd);
var newPrices = this.state.prices;
newPrices[x] = data.price_usd;
this.setState({prices: newPrices});
console.log(this.state.prices);
})
.catch((error) => {
console.log(error);
});
})(i);
}
}

Pokemon API, Promises javascript get data inside of array json

I have been working to make a small app to get the images and info from the pokemon api at http://pokeapi.co/ , I am following course using promises however I can get a group (example: water type) which give me 78 objects , each one with a resource_uri which is the data which give me the information of each pokemon.
Until now I have make this and I can get all the objects, however, now how can I make in order to get for each object push in the console.log (or later use them) all the 78pokemons with the data of each.
My code until now is this>
var $ = window.jQuery
var base = 'http://pokeapi.co/api/v1/egg/'
Promise.resolve($.get(base + '2'))
.then((results) =>
.then((results) => {
var pokechara = results.pokemon
var basechara = 'http://pokeapi.co'
var promises = []
for (let chara of pokechara){
var pokech = pokechara[i]
'${something}'
var pokechurl = basechara + pokechara[0].resource_uri
promises.push(Promise.resolve($.get(pokechurl)))
}
debugger
return Promise.all(promises)
})
.then((poke) => {
console.log(poke)
})
.catch((err) => {
debugger
})
I really wanted to make something with the api of yugioh.wikia but I dont see how I can get work because the problem with the Cros-server or header. To see a preview of what I am doing you can see at http://www.kengreg.com/yugiohapp/
Thanks in advance
Actually, in the code used in your reply to Alex, the string variables you use to call the api are the only thing wrong, the 'http://' part at the start is needed. Apart from that, your code works fine.
var $ = window.jQuery;
var base = 'http://pokeapi.co/api/v1/egg/';
Promise.resolve($.get(base + '2'))
.then((results) => {
var pokechara = results.pokemon;
var basechara = 'http://pokeapi.co/';
var promises = [];
for (var i in pokechara){
var pokech = pokechara[i];
var pokechurl = basechara + pokechara[0].resource_uri;
promises.push(Promise.resolve($.get(pokechurl)));
}
debugger
return Promise.all(promises);
})
.then((poke) => {
debugger;
console.log(poke);
})
.catch((err) => { debugger })
I left the debugger so you can checkout the results of the promises. The poke variable at the end should have the objects array you wanted.

Categories