I have most of my code written but I'm not sure what I'm doing wrong on this:
let url = 'https://cors-anywhere.herokuapp.com/https://newsapi.org/v2/top-headlines?sources=hacker-news&apiKey=3dcfcd098261443dae7c7d002f25c062';
fetch(url)
.then(r =>{
return r.json();
})
.then(data => {
let articles = data.articles;
let storyList = document.createElement("ul");
let body = document.querySelector("body");
body.appendChild(storyList);
})
articles.map(articles => {
let storyItem = document.createElement("li");
storyItem.innerHTML = 'a href = "' + articles.href + '">' + articles.title + "</a>";
storyList.appendChild(storyItem);
})
.catch(e => {
console.log('An error has occurred: ${e}');
});
I had taken out the < > from the API code and tried switching things around like switching some properties to say something different but could someone help me understand this a bit better? Thanks in advance!
There were several things that you were doing wrong.
No need to use a proxy when the API you are consuming allows cors requests.
You were trying to access the "articles" out of scope and before the promise was resolved
You were using the wrong method, IMO, on the "articles" array. From here: Array.prototype.map()
The map() method creates a new array with the results of calling a provided function on every element in the calling array.
but you were not trying create a new array, you just wanted to iterate the array's elements. That is what Array.prototype.forEach() is for.
You used single quotes ' on your template literal instead of back-ticks `
let url = 'https://newsapi.org/v2/top-headlines?sources=hacker-news&apiKey=3dcfcd098261443dae7c7d002f25c062';
fetch(url)
.then(response => {
return response.json();
})
.then(data => {
let list = document.createElement('ul');
document.querySelector("body").appendChild(list);
data.articles.forEach(article => {
let item = document.createElement('li');
item.innerHTML = '' + article.title + "";
list.appendChild(item);
});
})
.catch(e => {
console.log(`An error has occurred: ${e}`);
});
Related
I'm running fetch() in a for loop, looping through an array of strings, and looking to handle each fetch response using a unique value (the for loop variable count).
Is there a way to pass data through a fetch command that's unrelated to the target API and get it back in the response?
Here is the code I have so far. The corresponding HTML has a series of images (pic1, pic2, etc.). I currently have "pic1" hard-coded in the .then(data) response handler, but would like to make that variable.
for (var n = 0; n < arrayLength; n++) {
console.log('Just inside arrayLength for loop');
console.log('Search term '+ n +' = ' + lines[n]);
//Do something
fetch("https://ws.audioscrobbler.com/2.0?method=album.search&album="+ lines[n] + "&api_key=" + lastfm_apikey + "&format=json")
.then((response) => {
// handle the response
return response.json();
})
.then((data) => {
let tunes = data;
console.log('n: ' + n);
let albumArtURL = data.results.albummatches.album[0].image[3]['#text'];
console.log('albumArtURL: ' + albumArtURL);
document.getElementById("pic1").src = albumArtURL;
})
.catch(function(error) {
// handle the error
console.log('Error returned: ' + error);
});
}
I have reviewed the Last.FM API and there doesn't look like there's a way to just pass a string through from the request back through the response.
I think you are over thinking it. You have the data so reference it in your then function.
for (let n = 0; n < arrayLength; n++) {
const line = lines[n];
fetch(`https://ws.audioscrobbler.com/2.0?method=album.search&album=${line}&api_key=${lastfm_apikey}&format=json`)
.then((response) => response.json())
.then((data) => {
console.log(n, line);
})
.catch((error) => {
console.error('Error returned: ' + error);
});
}
my name is Jan, I have to do a project for high school, the fact is that I have made a code to access an api, but I cannot display the results of an array that has the api on the screen.
This is the code :
`
document.querySelector("button").addEventListener("click", getCoin);
function getCoin(){
let coin = document.querySelector("input").value.split(" ").join(" ")
console.log(coin)
fetch("https://open.er-api.com/v6/latest/" + coin)
.then (res => res.json())
.then (data => {
console.log(data.rates)
document.querySelector("#coinName").innerText = data.base_code
document.querySelector("#coinRates").innerText = data.rates
document.querySelector("#coinProvider").innerText = data.provider
document.querySelector("#coinTime").innerText = data.time_last_update_utc
document.querySelector("#coinProxTime").innerText = data.time_next_update_utc
})
}
`
It only works if I indicate a specific coin at document.querySelector("#coinRates").innerText = data.rates, and what I want is for it to show me all the values on the screen.
I would be very grateful if you could help me.
I have tried with a querySelectALL, also with the for loop, although I think I have done it wrong
Use Object.keys():
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
Object.keys(data).forEach( key => console.log( data[key] ) );
forEach-loop should do the job in your case.
like the following:
function getCoin() {
let coins = document.querySelectorAll("input");
console.log(coins);
coins.forEach((coin) => {
coin.value.split(" ").join(" ");
fetch("https://open.er-api.com/v6/latest/" + coin)
.then((res) => res.json())
.then((data) => {
console.log(data.rates);
document.querySelector("#coinName").innerText += data.base_code;
document.querySelector("#coinRates").innerText += data.rates;
document.querySelector("#coinProvider").innerText += data.provider;
document.querySelector("#coinTime").innerText +=
data.time_last_update_utc;
document.querySelector("#coinProxTime").innerText +=
data.time_next_update_utc;
});
});
}
I've been trying to make a program that spits out the definitions of a word list for a project. I am using https://dictionaryapi.dev/. I've never worked with web apis before, so can I get some help with this.
I've tried
var data = $.getJSON("https://api.dictionaryapi.dev/api/v2/entries/en/hello")
then
document.getElementById('output').innerHTML = data.meanings[1].definition
but it doesn't work. It says it can't find what meanings is.
You could use flatMap to retrieve just the definitions from the response:
const DICTIONARY_API_BASE_URL =
'https://api.dictionaryapi.dev/api/v2/entries/en/';
const DEFINITIONS_DIV = document.getElementById('definitions');
const fetchWordDefinitions = async word => {
console.log(`Making request for definitions of ${word}...`);
const response = await fetch(DICTIONARY_API_BASE_URL + word);
const json = await response.json();
return json[0].meanings
.flatMap(m => m.definitions)
.flatMap(d => d.definition);
};
const getWordDefinitions = () => {
const word = document.getElementById('word').value;
if (word == null || word == '') {
return alert('Error: You must enter a word to fetch');
}
DEFINITIONS_DIV.innerHTML = '';
fetchWordDefinitions(word)
.then(defintions => {
defintions.forEach(d => {
DEFINITIONS_DIV.innerHTML += `<p>${d}</p>`;
});
})
.catch(_ => {
DEFINITIONS_DIV.innerHTML += `<p>Error: Could not retrive any defintions for ${word}.</p>`;
});
};
* {
font-family: sans-serif
}
<!DOCTYPE html>
<html>
<body>
<h1>Fetch the definitions for a word!</h1>
<input type="text" id="word" name="word">
<input type="button" value="Fetch" onClick="getWordDefinitions()">
<div id="definitions"></div>
</body>
</html>
What I usually do with cases like this is to make use of the console.log() function.
fetch('https://api.dictionaryapi.dev/api/v2/entries/en/english')
.then(response => {
return response.json();
})
.then(word => {
console.log(word);
})
You can use Chrome developer tools by pressing F12. A console window will open in your browser, here you can expand the JSON response request returned from console.log(word); this will allow you to view each of the child elements. This should give you a better idea of how the structure of the JSON is formatted. Once you understand the structure you can remove the console.log(word); and assign it to a variable
var singleWordDefinition = word[0].meanings[0].definitions[0].definition;
Example Code:
function returnDefinition() {
fetch('https://api.dictionaryapi.dev/api/v2/entries/en/hello')
.then(response => {
return response.json();
})
.then(word => {
var singleWordDefinition = word[0].meanings[0].definitions[0].definition;
console.log("SINGLE: " + singleWordDefinition);
const wordDefinitionArr = word[0].meanings;
wordDefinitionArr.forEach(wordDefinition => {
console.log("FROM ARRAY: " + wordDefinition.definitions[0].definition);
});
})
};
Console output
I'm trying to create <optgroup>s that have subcategories pulled from an API. Currently, only the <optgroup>s are populating, but not the subcategories.
let select = document.querySelector("#category");
const categoriesURL = "INSERT_URL"
let str = "";
fetch(categoriesURL)
.then(response => response.json())
.then(data => {
data.forEach(category => {
let categoryTitle = category.title;
str += `<optgroup label=${categoryTitle}></optgroup>`
category.subcategories.forEach(sub => {
let subcategories_id = sub.subcategories_id;
let subcategoriesURL = `INSERT_URL/${subcategories_id}`;
fetch(subcategoriesURL)
.then(response => response.json())
.then(subData => {
str += `<option value=${sub.subcategories_id}>` + subData.title + "</option>";
})
})
})
select.innerHTML = "<option disabled selected>Select a category</option>" + str;
});
When defining your optgroup in the string, you immediately open and close the optgroup, effectively putting every option after the optgroup.
str += `<optgroup label=${categoryTitle}></optgroup>`
Leave the optgroup open in the aforementioned string.
However, the hard part is closing the string after all the fetch requests on the subcategories are complete. We can accomplish this with Promise.all and Array#map.
Loop over all the subcategories with map and return Promise that fetch returns in the loop. When all the fetch requests are done the code will continue to the then block that follows the Promise.all function. In that block you will have the ids and titles of all your subcategories collected in an array. Loop over array to append to your string.
After the loop, close the optgroup element.
fetch(categoriesURL)
.then(response => response.json())
.then(data => {
data.forEach(category => {
let categoryTitle = category.title;
str += `<optgroup label=${categoryTitle}>`;
Promise.all(category.subcategories.map(sub => {
let subcategories_id = sub.subcategories_id;
let subcategoriesURL = `INSERT_URL/${subcategories_id}`;
return fetch(subcategoriesURL)
.then(response => response.json())
.then(({ title }) => ({
title,
id: subcategories_id
}))
})).then(subData => {
subData.forEach(({ id, title }) => {
str += `<option value=${id}>${title}</option>`;
})
str += '</optgroup>';
});
})
select.innerHTML = "<option disabled selected>Select a category</option>" + str;
});
Though, overall this a very expensive script as it will create a lot of requests. If you have any say over the backend, then I'd advice that you send the all the data back in a single request and create your list based on that result.
I'm working on my front-end, and I've arrived at a roadblock. I'm trying to fetch data from my back-end, and it is actually fetching the data. But only after everything else? I'll show you.
$(function(){
function GetURLId() {
var url = window.location.href;
var path = url.substring(url.lastIndexOf('/') + 1);
var id = path.substring(path.lastIndexOf('?id=') + 4, path.lastIndexOf("?id") + 5)
return id;
}
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
})
});
});
So first I get which id I'm working with out of the URL. Then where the problem lays is the code under it. I'm able to fetch my data as it console.logs this:
id: 2
status: "Open"
damage: true
So the data does actually fetch from my back-end. But now, everytime I try to save the data it goes undefined. I've tried:
$(function(){
var rental = []; // Added an array
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
And:
var rental = []; // Added an array outside of the function
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
console.log(`${key}: ${data[key]}`);
rental.push(rental[key] = data[key]);
})
});
console.log(rental['id']); // Returns undefined
});
But! With the last one where the rental is outside of the function, I can actually call it in the console. And in the console it actually does return the value.
Inside Console:
> rental["id"]
< 2
Lastly I've tried to check the value of the key and value inside of the fetch, like this:
$(function(){
var url = 'https://localhost:5001/api/rental/byId/' + GetURLId();
fetch(url)
.then((resp) => resp.json())
.then(function(data) {
Object.keys(data).forEach(key => {
if(key == "status" && data[key] != "Reserved") {
console.log(`${key}: ${data[key]}`); // Returns damage: undefined 3 times
}
})
});
});
But this as well doesn't work. It returns damage: undefined 3 times in console.
So if anyone knows what is going on here it would be awesome!
Thanks alot in advance.
Fetch requests are asynchronous. This means that when you call fetch it might take a while to complete it, so JavaScript allows the rest of the code to continue without blocking. So logging anything to the console before your request has finished will obviously result in an empty array.
Also, Arrays are index-, not name based in JavaScript. However, because arrays are essentially objects it still works, but you should never do the following below.
var rental = [];
rental['id'] = 'foo';
console.log(rental['id']);
Instead use a plain object which is meant to be used that way.
var rental = {};
rental['id'] = 'foo';
console.log(rental['id']);
In your last example you seem to do everything just fine. Are you sure your fetched data does not have a value of undefined in its structure? It would help to see what the data looks like.
The answer: 2 errors in my code.
- First I didn't properly account for the asynchronous nature of the code.
- Second, when trying to fix it with another then block and executing my code in there. I didn't return a value in the proceeding then block, but the forEach instead.
fetch(url)
.then(resp => resp.json())
.then(data => {
var rentalStatus;
Object.keys(data).forEach(key => {
rental[key] = data[key];
if(key == "status") {
rentalStatus = data[key];
}
})
return rentalStatus;
})
.then(rentalStatus => {
console.log(rental["id"]); // This does return the id now!
if(rentalStatus == "Reserved") {
$("#assign-items").removeClass("d-none");
}
}).catch(error => {
console.log("Error:" + error);
});