I have a problem. I know I can use promises to fix this problem, but I do not understand how to use them in my case. I just want get id from a function in another file (let's call it callApi), and then use this id to call another function, callApi2. The problem is callApi2 runs before apiCall finishes.
ApiCariIdAktor = {
cariIdAktor: () => {
const apikey = APP_CONSTANT.api_key;
const url = `https://api.themoviedb.org/3/search/person?api_key=${apikey}&language=en-US&query=iko%20uwais&page=1&include_adult=false`;
let id = 0;
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
responseJson.results[0].id
})
.catch((error) => {
console.log(error)
})
return 10;
}
}
setID() {
this.state.id = ApiCariIdAktor.cariIdAktor();
}
async componentDidMount() {
this.setID();
await new Promise(resolve => {
setTimeout(resolve, 1000);
});
this.panggilApi2();
}
Related
i'm trying to fetch an endpoint that return a json object to display the result in my app.
this json return a list of online users, so i need to refresh this data every X seconds/minutes.
i've writed this code:
function getJustBlabData(url) {
return new Promise(resolve => {
const getData = fetch(url);
resolve(getData)
})
}
getJustBlabData('https://justblab.com/baxf/widget.php?q=online_usr')
.then((res) => res.json()
.then((data) => {
this.justBlab = data
this.loading = false
console.log(this.justBlab)
})
)
ive tried with setInterval like:
function getJustBlabData(url) {
return new Promise(resolve => {
setInterval(() => {
const getData = fetch(url);
resolve(getData)
}, 1000)
})
}
but i'm doing something wrong, but what?
Firstly, use fetch directly, since your getJustBlabData function is essentially just return fetch(url) wrapped in a new Promise - but since fetch already returns a Promise, there is no need for that code at all
i.e.
function getJustBlabData(url) {
return new Promise(resolve => {
const getData = fetch(url);
resolve(getData)
})
}
getJustBlabData(url).then ....
is equivalent (but in a lot of ways worse for error handling) to
fetch(url).then ....
If you want to do something every X seconds, do the whole thing in the interval
Like this
setInterval(() => {
this.loading = true;
fetch('https://justblab.com/baxf/widget.php?q=online_usr')
.then((res) => res.json())
.then((data) => {
this.justBlab = data;
this.loading = false;
console.log(this.justBlab);
});
}, 1000);
Now, this.justBlab gets updated every second
Note: Also, I've flattened your .then pyramid into a .then chain
to address the situation where requests could take longer than a second
(() => {
const processBlab = () => {
this.loading = true;
fetch('https://justblab.com/baxf/widget.php?q=online_usr')
.then((res) => res.json())
.then((data) => {
this.justBlab = data;
this.loading = false;
console.log(this.justBlab);
setTimeout(() => processBlab(), 1000);
});
processBlab();
})();
Only reason I put that all in a IIFE is to preserve this - as there is no context in the question as to what this is
You can use a promise to create a "wait" function and the restart the process again (get a new set of data) once that completes.
Here I used a 5 second delay between each cycle.
Doing it this way, if the server takes 10 seconds to reply this will do a new request 5 seconds after that response and avoids piling up requests.
let delayMSTime = 5000;
let howMany = 1;
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
function getJustBlabData(url) {
return new Promise(resolve => {
const getData = fetch(url);
resolve(getData);
})
}
function GoGetEm(myDelay) {
getJustBlabData('https://justblab.com/baxf/widget.php?q=online_usr')
.then((res) => res.json())
.then((data) => {
this.justBlab = data;
this.loading = false;
console.log(this.justBlab);
}).then(() => {
console.log("sleeeping for the "+howMany+" time:" + myDelay);
sleep(myDelay).then(() => {
howMany++;
GoGetEm(myDelay);
console.clear();
});
});
}
GoGetEm(delayMSTime);
So I have this fetch-api
let test = () => fetch(usd_api).then(response => response.json())
.then(data => data.exchange_rates.dash_usd);
Console log
let console_test = () => {console.log(test())}
How can use this number [[PromiseResult]]: 134.445... in the following function where the number 150 is.
function main(){
fetch(txs_api).then(response => response.json()).then(function(data) {
var amount = data.txs[0].vout[1].value;
if(amount == 150){
// SUCCESS!
$('#modal').modal('hide');
console.log('requests stopped');
clearInterval(interval);
}
})
}
let test = () => fetch(usd_api)
.then(response => response.json())
.then(data => data.exchange_rates.dash_usd);
You want too keep using the same promise, if you want to log the result of your promise you need to wait for it to be completed:
// with .then()
test().then(console.log);
// or with await if you can:
console.log(await test());
I figured it out. Don't know if it's the best way to do it but it's working.
function main(){
fetch(usd_api).then(response => response.json()).then(function(data) {
var dash_price = data.exchange_rates.dash_usd;
fetch(txs_api).then(response => response.json()).then(function(data) {
var amount = data.txs[0].vout[1].value;
if(amount == dash_price){
// SUCCESS!
$('#modal').modal('hide');
console.log('requests stopped');
clearInterval(interval);
}
})
})
}
Do not return value.
Because it returns to below function
function(data) {
return data.exchange_rates.dash_usd
}
If you want to return your value to a variable you have to use Promise like below.
let test = new Promise((resolve, reject) => {
fetch(usd_api).then(response => response.json())
.then(function (data) {
resolve(data.exchange_rates.dash_usd)
});
})
async function demo(){
let console_test = await test
console.log(console_test )
}
demo()
Note : Do not forget to use async and await
I'm working on a React project where I have a function that fetches paginated data recursively. This function is defined in another function, where I activate the loading screen with showLoading() at the start, where I'm calling the fetching data function in the body and deactivate the loading screen with hideLoading() at the end. The function:
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
getPlaylistDataRecursively(next_url)
}
})
}
getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}
I believe I can attach a promise to the getPlaylistDataRecursively call with the then keyword but I'm getting a TypeError: Cannot read property 'then' of undefined. Probably because getPlaylistDataRecursively doesn't return anything. How do I make sure that hideLoading is called after getPlaylistDataRecursively is done?
You always need to return a promise.
const fetchPlaylist = (playlistId) => {
showLoading()
const getPlaylistDataRecursively = (url) => {
return fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
.then(response => response.json())
.then(data => {
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
return getPlaylistDataRecursively(next_url)
}
})
}
return getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
.then(() => hideLoading());
}
Or, using async/await:
const fetchPlaylist = async (playlistId) => {
showLoading()
const getPlaylistDataRecursively = async (url) => {
const response = await fetch('/spotify/get-track-ids', {headers: {
'url': url
}})
const data = response.json()
console.log(data)
setTitles(data.title)
setArtists(data.artist)
setFeatures(data.features)
setIds(data.track_ids)
if (data.next_url) {
const next_url = data.next_url.replace('https://api.spotify.com/v1', '')
await getPlaylistDataRecursively(next_url)
}
}
await getPlaylistDataRecursively(`/playlists/${playlistId}/tracks/?offset=0&limit=100`)
hideLoading()
}
After troubleshooting with console.log/debugger it seems like I cannot iterate over my API generated array at the forEach method call in the function addListItem.
However I can see the pokemonNameList array being populated in the forEach iteration in the loadList function.
What am I doing wrong?
const apiUrl = 'https://pokeapi.co/api/v2/pokemon/?limit=15';
const pokemonNameList = [];
function getAll() {
return pokemonNameList;
}
function add(pokemon) {
if (typeof pokemon === 'object') {
pokemonNameList.push(pokemon);
}
}
function loadList() {
return fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
data.results.forEach((item) => {
fetch(item.url)
.then((response) => response.json())
.then((inneritem) => {
const pokemon = {
name: inneritem.name,
height: inneritem.height,
weight: inneritem.weight
};
add(pokemon);
console.log(pokemonNameList);// I can see the array here
});
});
})
.then(() => {
console.log(pokemonNameList);
})
.catch((e) => {
console.error(e);
});
}
function addListItem(pokemon) {
console.log('I cannot see this console log');//This does not show up
const card = document.createElement('li');
const cardbody = document.createElement('div');
const name = document.createElement('h1');
card.classList.add('card');
cardbody.classList.add('card-body');
name.classList.add('card-title');
name.innerText = pokemon.name;
cardbody.appendChild(name);
card.appendChild(cardbody);
pokemonList.appendChild(card);
}
loadList()
.then(() => {
getAll().forEach((item) => {
console.log('Hello from inside the forEach');//I cannot see this
addListItem(item);
});
})
.catch((e) => {
console.error(e);
});
The problem is that you are not waiting for the inner fetch(item.url)s so when you call getAll no item has been pushed yet.
you can do that by changing forEach to map, returning the promise and adding a promise.all... something like this:
function loadList() {
return fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
return Promise.all(data.results.map((item) => {
return fetch(item.url)
...
I created all the functions up to the place where you mentioned the error
const pokemonNameList = []; // Pokemon Array
const apiUrl = 'https://pokeapi.co/api/v2/pokemon/?limit=15'; // API URL
// To prevent duplicates, in case of calling the loadList function multiple times, i'm passing the index from the response, to replace the element at the same index
const add = (pokemon, index) => pokemonNameList[index] = (pokemon);
const getAll = _ => pokemonNameList; // Short arrow function to return pokemonNameList
async function loadList() {
const response = await fetch('https://pokeapi.co/api/v2/pokemon/?limit=5');
const result_1 = await response.json();
Promise.all(result_1.results.map((item, index) => fetch(item.url).then(response_1 => response_1.json()).then(({
name,
height,
weight
}) => add({
name,
height,
weight
}, index)))).then(() => getAll().forEach(pokemon => console.log(pokemon)));
}
app.js
import test from "./asyncTest";
test().then((result)=>{
//handle my result
});
asyncTest.js
const test = async cb => {
let data = await otherPromise();
let debounce = _.debounce(() => {
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then( => response.json())
.then(json => json );
}, 2000);
};
export default test;
The fetch result "json" I intend to return is unable to be the return value of "test" function since the value only available in an inner function scope such as debounce wrapper. Since above reason, I tried to pass a callback function and wrap the callback to be Promise function(pTest) as below.
const test = async cb => {
let debounce = _.debounce(() => {
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json())
.then(json => cb(null, json))
.catch(err => cb(err));
}, 2000);
};
const pTest = cb => {
return new Promise((resolve, reject) => {
test((err, data) => {
if (err) reject(err);
resolve(data);
});
});
};
export default pTest;
This way works for me, but I'm wondering if it's correct or are there any ways to solve this scenario?
The fetch API already returns a promise. Wrapping it in another Promise object is actually an anti-pattern. it is as simple as the code below:
/*export*/ async function test() {
let data = await otherPromise();
return fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(response => response.json())
.then(json => {
return {
json: json,
data: data
}
});
};
function otherPromise() {
return new Promise((resolve, reject) => {
resolve('test for data value');
});
}
// In index.js call
test().then(res => {
console.log(res)
});