Can't change array values in node route - javascript

I'm trying to set some values based in a conditional so I've decided to make a map in parent array to change some values, but the right values aren't returning for parent array.
app.get('/api/painel/mapa-processos/:idplanejamento/:rotina', (req, res) => {
let idLista = req.params.idplanejamento
let rotina = req.params.rotina
schemas.schemaOps.find({IDPLANEJAMENTO: idLista}).select('NUMEROOP')
.exec(async (err, result) => {
let listOps = result.map((result)=>{return result.NUMEROOP})
const connection = await oracleDB.connect()
let lastLancamentos = (await connection.execute(queriesOracle.lastLancamentos(listOps))).rows
lastLancamentos.map(async (row) => {
let lastAptoMobile = (await connection.execute(queriesOracle.lastAptoMobile(row[0]))).rows
if (lastAptoMobile.length > 0){
if (row[2] < lastAptoMobile[0][1]) {
row[1] = lastAptoMobile[0][0]
row[2] = lastAptoMobile[0][1]
row[3] = lastAptoMobile[0][3]
row[4] = null
row[5] = lastAptoMobile[0][2]
row[8] = lastAptoMobile[0][4]
console.log(row)
}}
return row
})
connection.close()
res.json(lastLancamentos)
})
})

Related

Delay script with setTimeout()

I'm trying to display some data from google - the script below works for pulling the data - but I want to add a delay to it running so there's time for it to process the data when a change is made.
I've tried adding setTimeout() to the whole piece of code, but when I add it it turns back blank.
Any ideas?
https://codepen.io/jameswill77/pen/PoREWmK
const sheetId = '1Fa0SgniGrmW_0DCQriR6-XYj2eiRayTK_9HZG9BQYok';
const base = `https://docs.google.com/spreadsheets/d/${sheetId}/gviz/tq?`;
const sheetName = 'sheet 1';
const query = encodeURIComponent('Select *')
const url = `${base}&sheet=${sheetName}&tq=${query}`
const data = []
document.addEventListener('DOMContentLoaded', init)
const output = document.querySelector('.output')
function init() {
fetch(url)
.then(res => res.text())
.then(rep => {
//Remove additional text and extract only JSON:
const jsonData = JSON.parse(rep.substring(47).slice(0, -2));
console.log(rep)
const colz = [];
const tr = document.createElement('tr');
//Extract column labels
jsonData.table.cols.forEach((heading) => {
if (heading.label) {
let column = heading.label;
colz.push(column);
const th = document.createElement('th');
th.innerText = column;
tr.appendChild(th);
}
})
output.appendChild(tr);
//extract row data:
jsonData.table.rows.forEach((rowData) => {
const row = {};
colz.forEach((ele, ind) => {
row[ele] = (rowData.c[ind] != null) ? rowData.c[ind].v : '';
})
data.push(row);
})
processRows(data);
})
}
function processRows(json) {
json.forEach((row) => {
const tr = document.createElement('tr');
const keys = Object.keys(row);
keys.forEach((key) => {
const td = document.createElement('td');
td.textContent = row[key];
tr.appendChild(td);
})
output.appendChild(tr);
})
}
<div class="output"></div>
document.addEventListener('DOMContentLoaded', () => {
setTimeout(init, 3000);
});
Is this behaviour what you are looking for?

JS Pagination Using Promises

I'm attempting to make an API call using promises. The API is paginated and as such, depending on the headers in that first API call make more to get the rest of the results if need be.
Here's what I have so far:
const get = (url, pageNo) => {
var options = {
url: url,
headers: {
'Authorization': `Token token=${apiToken}`
},
json: true,
page: pageNo
};
return new Promise((resolve, reject) => {
request.get(options, (err, resp) => {
err ? reject(err) : resolve(resp);
})
});
};
Using get() to loop and get all responses:
const getAll = (plannerId, timestamp, range) => {
const plannerBookingsUrl = new URL(
`/api/planners/${plannerId}/bookings?since=${timestamp}&range=${range}`,
baseUrl
);
let response = get(plannerBookingsUrl, 1);
let bookings = [];
bookings.push(response);
response.then(results => {
let moreRequests = true;
let currentPage = 1;
const totalPages = parseInt(results.headers['x-total-pages']);
while (moreRequests) {
if (currentPage < totalPages) {
nextBatch = get(plannerBookingsUrl, currentPage + 1);
bookings.push(nextBatch);
currentPage++;
} else {
moreRequests = false;
}
}
});
return Promise.all(bookings);
};
Main() where I'm using getAll(...):
const main = () => {
const response = getAll(
'11716',
'2020-02-27',
'7'
);
response.then(results => {
console.log(results);
.catch(error => console.log(error))
};
main();
This returns the initial promise but not the remaining promises.
What I'm really have a problem with is reading the first API, making the remainder and returning them all together to be using in my main function.
Any help would be much appreciated!
Thanks.
You could put all your fetching logic inside the while loop. The way you get your bookings is the same, except for the first time where you need to get a little more information on the amount of pages.
Accomplish this by making your function async and check the first time of the loop if the totalPages value is already known. If it's not, await the response and get the info from the headers, and otherwise just push the response to the bookings array.
const getAll = async (plannerId, timestamp, range) => {
const plannerBookingsUrl = new URL(
`/api/planners/${plannerId}/bookings?since=${timestamp}&range=${range}`,
baseUrl
);
let bookings = [];
let currentPage = 1;
let totalPages = null;
while (totalPages === null || currentPage < totalPages) {
let response = get(plannerBookingsUrl, currentPage);
if (totalPages === null) {
let results = await response;
totalPages = parseInt(results.headers['x-total-pages']);
}
bookings.push(response);
currentPage++;
}
return Promise.all(bookings);
};
The problem is that you are returning Promise.all(bookings) outside response.then callback, so at this point bookings contains only the first call get(plannerBookingsUrl, 1).
Here is a possible solution using async:
const getAll = async (plannerId, timestamp, range) => {
const plannerBookingsUrl = new URL(
`/api/planners/${plannerId}/bookings?since=${timestamp}&range=${range}`,
baseUrl
);
let response = get(plannerBookingsUrl, 1);
let bookings = [];
bookings.push(response);
const results = await response; // wait for results here
let moreRequests = true;
let currentPage = 1;
const totalPages = parseInt(results.headers['x-total-pages']);
while (moreRequests) {
if (currentPage < totalPages) {
nextBatch = get(plannerBookingsUrl, currentPage + 1);
bookings.push(nextBatch);
currentPage++;
} else {
moreRequests = false;
}
}
return Promise.all(bookings); // bookings now contains every next batch
};
adapt on main() function:
const main = async () => {
const results = await getAll(
'11716',
'2020-02-27',
'7'
);
...
};
main();

Discord.js Bot to print out an array from MySQL in a single .addField in javascript

I'd like to fetch usernames from a MySQL table and want the bot to print them out in an embedded message.
this is what I have so far:
let get_winners = `SELECT UserName FROM resultsoflastbet WHERE oldAmount < newAmount`;
let query2 = mysq.query(get_winners, (err, results) => {
if(err){
}
Object.keys(results).forEach(function (key) {
const row = results[key];
let winners = row.UserName;
let winnersArr = winners.split("\n");
let botembed = new Discord.RichEmbed()
.setColor("#15f153")
.addField("Winners:", `${winnersArr}`);
message.channel.send(botembed);
});
});
which will send the message:
Winners:
WinnerNo.1
Winners:
WinnerNo.2
Winners:
WinnerNo.3
.
.
.
but what I want is that it prints it out like this:
Winners:
WinnerNo.1
WinnerNo.2
WinnerNo.2
how do I do that?
also when I want to Tag each of them how do I do that as well?
You have to do it this way:
let get_winners = `SELECT UserName FROM resultsoflastbet WHERE oldAmount < newAmount`;
let query2 = mysq.query(get_winners, (err, results) => {
if(err){
}
let botembed = new Discord.RichEmbed()
.setColor("#15f153");
let winnersString = "";
Object.keys(results).forEach(function (key) {
const row = results[key];
let winners = row.UserName;
let winnersArr = winners.split("\n");
winnersString += `\n${winnersArr}`;
});
botembed.addField("Winners:", winnersString);
message.channel.send(botembed);
});
This will create a new empty string and fill it with each winner!

JSON values not displaying when outputting multiple values (array) to HTML

I am iterating over a JSON object via fetch().
I would like to access one of the objects within the objects and iterated over it accessing the key: value pairs and output the values to HTML via list items.
When I try to output the values I only get the last value of the powerstats (there are 6)
What do I need to change here to have all values display properly on my page?
I tried to create a for loop and iterate over the value.length, however value.length gives me 2 as an answer.
Feel free to use the provided api key.
function get_hero(rand_number) {
const api_key = '10156555926000957';
let hero_id = rand_number;
let hero_url = `https://www.superheroapi.com/api/${api_key}/${hero_id}`;
fetch(hero_url)
.then(res => {
return res.json();
})
.then( data => {
let ps = data.powerstats;
Object.entries(ps).forEach(([key, value]) => {
console.log(key + ' - ' + value) // key - value
console.log(value.length)
const smt = `<ul>
<li>${value}</li>
<li>${value}</li>
<li>${value}</li>
<li>${value}</li>
<li>${value}</li>
<li>${value}</li>
</ul>`;
const power_stats = document.getElementById('powerstats');
power_stats.innerHTML = smt;
})
})
.catch(function() {
console.log('error')
})
}
Sry didn't had coffee yet, XD
so your problem is that you replace all of the power_stats.innerHTML = smt; with smt over and over again. You want to use element.appendChild(element) to ADD to a list. Not overwrite
.then(data => {
const ps = data.powerstats;
const power_stats = document.getElementById('powerstats');
const list = document.createElement(`ul`)
power_stats.appendChild(list)
Object.entries(ps).forEach(([key, value]) => {
console.log(key + ' - ' + value) // key - value
console.log(value.length)
const smt = document.createElement(`li`)
smt.innerText = `The heroes ${key} is ${value}`
list.appendChild(smt)
})
})
Currently you function return void, so you don't wait for fetch, so you should return promise:
function get_hero(rand_number) {
const api_key = '10156555926000957';
let hero_id = rand_number;
let hero_url = `https://www.superheroapi.com/api/${api_key}/${hero_id}`;
return fetch(hero_url)
.then(res => {
return res.json();
})
.then( data => {
let ps = data.powerstats;
Object.entries(ps).forEach(([key, value]) => {
console.log(key + ' - ' + value) // key - value
console.log(value.length)
const smt = `<ul>
<li>${value}</li>
</ul>`;
const power_stats = document.getElementById('powerstats');
power_stats.innerHTML = smt;
})
})
.catch(function() {
console.log('error')
})
}
Using:
get_hero(123).then(() => console.log('done!'));
(for me https://www.superheroapi.com/ is not responding, so maybe it is not the only problem)

Scraping IMDb episodes using Cheerio.js - only first page of TV episodes is returned

Working on scraping TV episodes from IMDb (Breaking Bad in the example below). The problem is when implementing the for loop, only the first iteration of j is returned.
My assumption is the return statement is exiting the loop but I'm unsure how to fix the problem.
const fetch = require('node-fetch');
const cheerio = require('cheerio');
const searchUrl = 'https://www.imdb.com/find?s=tt&ttype=tv&ref_=fn_tv&q=';
const movieUrl = 'https://www.imdb.com/title/';
async function getEpisodes(searchTerm) {
//const imdbID = await getID(searchTerm);
//const numSeasons = await getSeasons(imdbID);
const imdbID = 'tt0903747';
const numSeasons = 5;
const episodes = [];
for (let j = 1; j <= numSeasons; j++) {
return fetch(`${movieUrl}${imdbID}/episodes?season=${j}`)
.then(response => response.text())
.then(body => {
const $ = cheerio.load(body);
$('div[itemProp="episodes"]').each(function (i, element) {
const airdate = $(element).find('.airdate').text().trim();
const episodeTitle = $(element).find('a[itemProp="name"]').text().trim();
const votes = $(element).find('.ipl-rating-star__total-votes').text().trim().match(/\(([^)]+)\)/)[1];
const rating = $(element).find('.ipl-rating-star ').find('.ipl-rating-star__rating').text().trim().slice(0, 3);
episode = {
season: j,
episodeTitle,
airdate,
votes,
rating
};
episodes.push(episode);
});
return episodes; //Only season 1 is returned.
});
}
}
Let's rewrite the function using async await style. This way we make sure we fire fetch numSeasons times, await all of them, and process them one by one.
async function processResponse(response, season) {
const body = await response.text();
const $ = cheerio.load(body);
let episodes = [];
$('div[itemProp="episodes"]').each(function (i, element) {
const airdate = $(element).find('.airdate').text().trim();
const episodeTitle = $(element).find('a[itemProp="name"]').text().trim();
const votes = $(element).find('.ipl-rating-star__total-votes').text().trim().match(/\(([^)]+)\)/)[1];
const rating = $(element).find('.ipl-rating-star ').find('.ipl-rating-star__rating').text().trim().slice(0, 3);
episode = {
season,
episodeTitle,
airdate,
votes,
rating
};
episodes.push(episode);
});
return episodes;
}
async function getEpisodes(searchTerm) {
//const imdbID = await getID(searchTerm);
//const numSeasons = await getSeasons(imdbID);
const imdbID = 'tt0903747';
const numSeasons = 5;
let promises = [];
for (let j = 1; j <= numSeasons; j++) {
promises.push(fetch(`${movieUrl}${imdbID}/episodes?season=${j}`));
}
const responses = await Promise.all(promises);
return responses.reduce((accumulator, response, index) => {
return accumulator.concat(await processResponse(response, index + 1));
}, []);
}

Categories

Resources