Here is my code
export default class Application extends EventEmitter {
constructor() {
super();
this.config = config;
this.data = {
planets: [planetData]
};
this.init();
let url;
let count;
let planetData = []
let promises = [];
//turn through the pages
for (let p = 1; p < 7; p++) {
url = `https://swapi.boom.dev/api/planets?page=${p}`;
//fetch data
promises.push(fetch(url).then(res => res.json())
.then(data => {
//push data to array
for (let i = 0; i < data.results.length; i++) {
planetData = planetData.concat(data.results[i]);
}
}));
}
Promise.all(promises)
.then(() => {
console.log(planetData.length, '=>', planetData);
})
}
I need help assigning the planetData array to this.data{}. I tried the following this.data{ planets: [planetData], but it gave an error "Cannot access 'planetData' before initialization", which was expected. My syntax is also probably wrong, but I'm really new to JS.
You should assign the variable after the planetData array has been populated.
Perhaps you can try something like this:
Promise.all(promises)
.then(() => {
console.log(planetData.length, '=>', planetData);
})
.then(() => {
this.data.planets = planetData;
})
You can assign planetData to the key planets later in your code using:
this.data.planets = planetData;
Related
So this function uses fetch to get a list of team names and pass them on to the getTeams() function
export function process_all_teams(func) {
fetch('/teams')
.then((response) => {
return response.json();
})
.then((result) => {
return getTeams(result);
})
.then((results) => {
js_avg_goals(results);
})
.catch((error) => console.log(error))
}
The getTeams function then uses the names to retrieve the list of players from the /teams/<team_name> url to create and return an array of js Team objects.
function getTeams(result){
let promises = Array(12);
for(let i=0; i < result.length; i++){
let url = '/teams/' + result[i];
promises[i] = fetch(url).then((response) => {return response.json()});
}
let teams = Array(12);
Promise.all(promises)
.then((res) => {
for(let i=0; i < res.length; i++){
teams[i] = new Team(res[i]);
}
})
.catch(() => console.log("There was an error in getTeams"))
return teams;
}
In the js_avg_goals function I'm trying to log out results[0] but it returns 'undefined' while results returns the actual array of Team objects.
export function js_avg_goals(results) {
console.log(results);
console.log(results[0]);
}
This is the Team constructor. The first item of the array res is the team name while the rest are players that are represented as player objects converted to json.
function Team(res){
this.name = res[0];
this.players = res.slice(-15);
}
I don't understand why this is happening somebody please help me.
Promise.all returns a new promise.
Modify getTeams to return that promise, something like this:
return Promise.all(promises)
.then(res => res.map(r => new Team(r)))
.catch(() => console.log("There was an error in getTeams"))
export function fetchNews(data) {
const news = []
var numOfArticlesArray = fetchNewsPreprocessing(data)
data.map((interest, index) => {
fetch(`https://newsapi.org/v2/top-headlines?country=us&category=${interest}&apiKey=`)
.then(res => res.json())
.then(res => res.articles)
.then(res => {
for (let i = 0; i < numOfArticlesArray[index]; i++) {
news.push(res[i])
}
})
.catch(err => console.log(err))
})
console.log(news);
}
So here is the function, my issue is that I'm getting this console.log(news); before I finish appending to my news array in here news.push(res[i]) which results in a blank array.
I tried adding async and await to the function like this async function fetchNews(data) and await data.map((interest, index) => { but no use.
thanks in advance.
Do you want to execute your fetch() calls serially, or in parallel?
If you want to execute them serially then something like this will work:
export function fetchNews(data) {
const news = [];
const numOfArticlesArray = fetchNewsPreprocessing(data);
data.map( async (interest, index) => {
const url = `https://newsapi.org/v2/top-headlines?country=us&category=${interest}&apiKey=`;
try {
const res = await fetch(url).then(res => res.json());
const articles = res.articles;
for ( let i = 0 ; i < numOfArticlesArray[index] ; i++ ) {
news.push(articles[i]);
}
} catch (err) {
console.log(err);
}
})
console.log(news);
}
If you want to execute them in parallel, however, then something like this is what you want:
export async function fetchNews(data) {
const news = [];
const numOfArticlesArray = fetchNewsPreprocessing(data);
const requests = data.map( (interest, index) => {
const url = `https://newsapi.org/v2/top-headlines?country=us&category=${interest}&apiKey=`;
const res = fetch(url).then(res => res.json());
return res;
})
const responses = await Promise.all( requests );
for ( const i = 0 ; i < responses.length ; ++i ) {
const res = responses[i];
const articles = res.articles;
for ( let j = 0 ; j < numOfArticlesArray[i] ; ++j ) {
news.push(articles[j]);
}
}
console.log(news);
}
You should put await in front of fetch() instead. For example, this piece of code will output the news array with the test element:
async function fetchNews(data) {
let news = [];
await fetch(url).then(() => news.push('test'));
console.log(news)
}
i have an a data using fetch on some API and looks like this.
and i'm fetching this data (as you can see), i'm using a promise here is the code
data-source
const baseUrl = "https://api.musixmatch.com/ws/1.1";
const apiKey = "78fa4727ab9c4495d4fc07dae75f775b";
const chartTrackPopular = "chart.tracks.get?
chart_name=top&page=1&page_size=5&country=jp&f_has_lyrics=1";
const chartTrackAll = "chart.tracks.get?chart_name=top&page=1&page_size=5&country=us&f_has_lyrics=1";
class DataSource {
// initialize the data
static getPopularLirik(){
return fetch(`${baseUrl}/${chartTrackPopular}&apikey=${apiKey}`)
.then(response => {
return response.json();
})
.then(responseJson => {
if(responseJson.message.body.track_list) {
return Promise.resolve(responseJson.message.body.track_list);
} else {
return Promise.reject(`error`)
}
})
.catch(error => {
console.log(error);
})
}
}
export default DataSource;
i get the data but when i try to loop it, i cant get the data. Here is how i want to get the data
popular-list.js
import './popular-item.js'
class PopularList extends HTMLElement {
constructor(){
super();
this.shadowDOM = this.attachShadow({mode: "open"});
}
set items(item){
this._item = item;
this.render();
}
render(){
this.shadowDOM.innerHTML = "";
this._item.forEach(musicitem => {
const itemElements = document.createElement("popular-item");
itemElements.items = musicitem;
// this.shadowDOM.appendChild(itemElements);
})
// let result = DataSource.getPopularLirik();
// console.log(this._item.track);
}
};
customElements.define("popular-list", PopularList);
and this is the error i got
VM55555 popular-list.js:20 Uncaught TypeError: this._item.forEach is not a function
at HTMLElement.render (VM55555 popular-list.js:20)
at HTMLElement.set items [as items] (VM55555 popular-list.js:15)
at renderResult (VM55554 main.js:13)
at HTMLDocument.main (VM55554 main.js:19
i don't know how and why this can be happened, i thought if i try to loop the data i can get the value but i dont even cant to forEach it. How do i resolve this?
I am trying to receive data via stdin which I have working:
const fs = require('fs');
const readStream = process.stdin;
readStream.pause();
readStream.setEncoding('utf8');
readStream.on('data', (data) => {
console.log(data);
});
readStream.resume();
Now what I need to do is store it as a variable so I can do some calculations before I return it via stdout.
Every time I try to so anything with it, like push certain data to an array it repeats the data until the stdin has finished, and I cant access it after it has finished. I cant find any resources online to help me.
You can use ReadableStream to process asynchronous tasks. Call .getReader() of ReadableStream instance to get an object which has a .read() method which when called returns an object having value and done properties. The controller passed to the constructor can queue tasks to be performed, the call to read() reads the enqueued data and sets the data at value property.
let n = 0;
let letters = "abcdefghijklmnopqrstuvwxyz";
const results = [];
let readableStream = new ReadableStream({
pull(controller) {
if (n < letters.length) controller.enqueue(letters[n++])
else controller.close();
}
});
let reader = readableStream.getReader();
let processStream = ({value, done}) => {
if (done) return reader.closed.then(() => results);
console.log(value);
// do stuff
let next = new Promise(resolve =>
setTimeout(() => {results.push(value); resolve()}
, Math.floor(Math.random() * 1200))
);
return next.then(() => reader.read())
.then(data => processStream(data));
}
reader.read()
.then(data => processStream(data))
.then(res => console.log(res));
You can also pipe the ReadableStream and .pipeTo() method of the instance to pipe the enqueued data to a WritableStream instance, where tasks can be performed at both read and write portions of the stream.
const letters = "abcdefghijklmnopqrstuvwxyz";
let RSController = class {
constructor(input) {
this.input = input;
this.n = 0;
}
async pull(controller) {
if (this.n < this.input.length) {
let curr = await this.handleData(this.input[this.n]);
++this.n;
controller.enqueue(curr);
} else {
this.n = 0;
controller.close();
}
}
cancel(err) {
console.log(err)
}
handleData(data) {
return new Promise(resolve => {
// do stuff
setTimeout(() => {
resolve(data)
}, Math.floor(Math.random() * 750))
})
}
}
let WSController = class {
constructor(arr = []) {
this.results = arr;
}
write(data) {
let dataUp = data.toUpperCase();
console.log(data, dataUp);
this.results.push([data, dataUp]);
}
close() {
console.log(JSON.stringify(this.results, null, 2));
}
abort(e) {
console.error(e);
}
}
let rscontroller = new RSController(letters);
let readableStream = new ReadableStream(rscontroller);
let wscontroller = new WSController([]);
let writableStream = new WritableStream(wscontroller);
readableStream
.pipeTo(writableStream);
I'm using mocha and zombie.
My goal is to load data from website <a> tags from website then query name and href. So far this is working:
const Browser = require('zombie')
const browser = new Browser()
browser.visit('page', () => {
let temp = browser.document.querySelectorAll('a selector')
for (let i = 0; i < temp.length; i++) {
browsers.push({ name: temp[i].innerHTML, url: temp[i].href })
}
delete temp
})
My next step would be using this data in testing.
const data = [{ name: 'name', url: 'test' }]
describe('test with for', () => {
for (let i = 0; i < data.length; i++) {
it(data[i].name, () => {
// test code with url of data[i]
})
}
})
The only problem I have is that data array is filled asynchronously and it has to be present at time of invoking it function.
I tryed using before but i saw that it does not make sence here (because of invoking async function don't stop code to execute and only function pased in it can depend on async data)
So I tryed to do this using Promise but it also failed.
const data = []
new Promise((resolve, reject) => {
// filing data
resolve()
}).then(() => {
describe('...', () => {
for (let i = 0; i < data.length; i++) {
it (data[i].name, () => {})
}
})
})
I looked at mocha documentation and didn't find solution :/
How should I solve this problem?
Ok i found solution, problem was my mistake i forgot to remove describe inwith my browser reading was contained that's why --delay did not work.
Running code:
const { describe, it } = require('mocha')
const { assert, expect } = chai = require('chai')
const Browser = require('zombie')
const browser = new Browser()
const browsers = []
new Promise((resolve, reject) => {
browser.visit('site', () => {
let temp = browser.document.querySelectorAll('selector')
for (let i = 0; i < temp.length; i++) {
browsers.push({ name: temp[i].innerHTML, url: temp[i].href })
}
delete temp
resolve()
})
}).then(() => {
describe('Get browser name', () => {
for (let i = 0; i < browsers.length; i++) {
it(browsers[i].name, () => {
})
}
})
run()
})