actually I'm facing a problem with Promises, a miss understanding surely.
I have an array with a list of ids that I use to make an API call that I'm sure it's valid and working. So I have to make foreach element in this list an API call => Promise.
I read about promises and I find this clean way to make it :
clean(){
/** Here, I'm just cleaning invalid ids to avoid a silenced map. I tried the
whole output in the API explorator, and it works well*/
this.facebook.objectIdsToDelete.forEach(element => {
let index = this.facebook.objectIdsToFilter.indexOf(element);
this.facebook.objectIdsToFilter.splice(index, 1);
});
Promise.all(this.facebook.objectIdsToFilter.map(value=>{
return this.facebook.callApiLikes(value);
}))
.then((responses) => {
this.debogger.debogSomething(responses);
})
.catch((reason) => {
this.debogger.debogSomething(reason);
})
}
debogger => it's a popup to show object content.
this.facebook.objecIdsToFilter => is a string[]
This popup do not raise, nothing happens.
Where I'm doing wrong ?
Related
I'm having some issues with the "Promise.all" method.
Bascially, I have an array of URL (here is a simple one if you guys want to test :
const urlArray = [
"https://coverartarchive.org/release/985adeec-a1fd-4e79-899d-10c54b6af299",
"https://coverartarchive.org/release/4c54ee58-86df-3ba5-aaad-6b284293141b",
"https://coverartarchive.org/release/cd8e5736-ec8c-3c4d-a231-ac097877d87a",
"https://coverartarchive.org/release/b9b7641f-9389-342e-8be9-e463bd52fdb9",
"https://coverartarchive.org/release/b6206cad-15eb-3a95-b67e-1f49849e5fbd",
"https://coverartarchive.org/release/db425753-965f-4881-955b-8cd3ef65d1e6",
"https://coverartarchive.org/release/fa4f230a-e78c-32a8-bec8-3a7425aba9d2",
"https://coverartarchive.org/release/fa023617-1585-4ae6-81b6-1a07c47ecb2a",
"https://coverartarchive.org/release/61782e1c-67a2-487c-8324-6431c628cad8",
"https://coverartarchive.org/release/b16e94f3-ad3b-4e3b-9fad-0ef3d2a0958e",
"https://coverartarchive.org/release/37e7091f-9ebc-4ac8-875b-5c88f7e5fba8",
"https://coverartarchive.org/release/a63b6cc9-899c-447d-b0e6-d1e439379eb2",
"https://coverartarchive.org/release/d2d3df43-65c4-499e-90d2-22a157cc7dea",
"https://coverartarchive.org/release/9cb95cac-4a0d-4fbb-9237-544a99f29b57",
"https://coverartarchive.org/release/7cf87b52-47e3-4d12-8890-53a910792b70"
]
Normally, when a promise is resolved, it should return a JSON object, has seen when you enter one of those URLs above in your browser with infos about cover arts for an album release.
So I have tried using Promise.all using this array and see what goes, but I simply can't get something to work : the json() method. I have tried several ways to handle this, found on stackoverflow or elsewhere on the internet, I just always get the "Uncaught (in promise) TypeError: response.json is not a function"
Here are several things I tried :
Promise.all(urlArray)
.then(toJSON)
.then((jsonObjects) => console.log(jsonObjects));
function toJSON(responses) {
if (!Array.isArray(responses)) {
// also handle the non array case
responses = [responses];
}
return Promise.all(responses.map((response) => response.json()));
}
Same thing I guess but without helper
Promise.all(urlArray)
.then((res) => {
const responses = res.map((response) => response.json());
return Promise.all(responses);
})
.then((data) => console.log(data));
The worst thing is, I did manage to do it a few days ago, then changed my mind about how to go with this, and I just can't find how I solved this the first time around. If you guys have any idea what I'm doing wrong, don't hesitate to point it out and scold me about it !
Cheers
Your urlArray is an array of plain strings, not an array of requests. You never actually make any network requests in your code - you don't have any Promises.
Map the array of request URLs to an array of Promises first.
const urlArray = [
"https://coverartarchive.org/release/985adeec-a1fd-4e79-899d-10c54b6af299",
"https://coverartarchive.org/release/4c54ee58-86df-3ba5-aaad-6b284293141b",
"https://coverartarchive.org/release/cd8e5736-ec8c-3c4d-a231-ac097877d87a",
"https://coverartarchive.org/release/b9b7641f-9389-342e-8be9-e463bd52fdb9",
"https://coverartarchive.org/release/b6206cad-15eb-3a95-b67e-1f49849e5fbd",
"https://coverartarchive.org/release/db425753-965f-4881-955b-8cd3ef65d1e6",
"https://coverartarchive.org/release/fa4f230a-e78c-32a8-bec8-3a7425aba9d2",
"https://coverartarchive.org/release/fa023617-1585-4ae6-81b6-1a07c47ecb2a",
"https://coverartarchive.org/release/61782e1c-67a2-487c-8324-6431c628cad8",
"https://coverartarchive.org/release/b16e94f3-ad3b-4e3b-9fad-0ef3d2a0958e",
"https://coverartarchive.org/release/37e7091f-9ebc-4ac8-875b-5c88f7e5fba8",
"https://coverartarchive.org/release/a63b6cc9-899c-447d-b0e6-d1e439379eb2",
"https://coverartarchive.org/release/d2d3df43-65c4-499e-90d2-22a157cc7dea",
"https://coverartarchive.org/release/9cb95cac-4a0d-4fbb-9237-544a99f29b57",
"https://coverartarchive.org/release/7cf87b52-47e3-4d12-8890-53a910792b70"
]
Promise.all(
urlArray.map(
url => fetch(url).then(res => res.json())
)
)
.then((results) => {
console.log('got all results');
// use results here
});
I'm working with Cloud Functions for Firebase, and I get a timeout with some of my functions. I'm pretty new with JavaScript. It looks like I need to put a for inside a promise, and I get some problems. The code actually get off from for too early, and I think he make this in a long time. Do you have some way to improve this code and make the code faster?
exports.firebaseFunctions = functions.database.ref("mess/{pushId}").onUpdate(event => {
//first i get event val and a object inside a firebase
const original = event.data.val();
const users = original.uids; // THIS ITS ALL USERS UIDS!!
// so fist i get all users uids and put inside a array
let usersUids = [];
for (let key in users) {
usersUids.push(users[key]);
}
// so now i gonna make a promise for use all this uids and get token's device
//and save them inside a another child in firebase!!
return new Promise((resolve) => {
let userTokens = [];
usersUids.forEach(element => {
admin.database().ref('users/' + element).child('token').once('value', snapShot => {
if (snapShot.val()) { // if token exist put him inside a array
userTokens.push(snapShot.val());
}
})
})
resolve({
userTokens
})
}) // now i make then here, from get userTokens and save in another child inside a firebase database
.then((res) => {
return admin.database().ref("USERS/TOKENS").push({
userTokens: res,
})
})
})
You are making network requests with firebase, so maybe that's why it's slow. You are making one request per user, so if you have 100 ids there, it might as well take a while.
But there's another problem that I notice, that is: you are just resolving to an empty list. To wait for several promises, create an array of promises, and then use Promise.all to create a promise that waits for all of them in parallel.
When you call resolve, you have already done the forEach, and you have started every promise, but they have not been added to the list yet. To make it better, chance it to a map and collect all the returned promises, and then return Promise.all.
I originally had only one URL to fetch data, and my app worked flawlessly. But then I realized I had to use two different URLs to fetch the data I needed. So I changed the code a little bit. Everything is pretty much the same except for the getData function, where I used map to iterate the list of URLs and fetch the data. My app is really buggy now.
Problems:
When I search for a streamer, it sometimes never renders the result on the page. And the message "search for your favorite streamer!" doesn't disappear even though this.state.value is now NOT equal to ' '. But when I change the input, it gets rendered out of nowhere.
It sometimes fails to render the data fetched and I get the FinderResultContainer rendered with no data in it. (No name, no img, no offline/online.)
What is exactly happening here? I feel like it is because I am not using the component life cycle methods. If so, then what exactly do I need to do? I am a total beginner, so I need to some guidance.
getData(value) {
let streamerData = [];
let streamerInfo = {};
let urls = ['https://wind-bow.gomix.me/twitch-api/streams/' + value, 'https://wind-bow.gomix.me/twitch-api/users/' + value];
urls.map(function(each, index) {
fetch(each).then((response) =>
response.json()
).then((streamer) => streamerData.push(streamer)).then(()=>streamerInfo[index]=streamerData[index]).then(()=>{if (index === urls.length-1){this.setState({streamer: streamerData})}})},this)
}
https://codepen.io/brood915/pen/OWQpmy
fetch is asynchronous and returns a promise, so you don't know exactly when it'll be done. You can use Promise.all() to wait every promise to resolve and then work with the data (note that all promises will execute at the same time, so if you have a large list of urls you will be sending tons of request per second).
Edit: I saw your pen and simplified the code, this works fine to me.
No blank component here. Note that you only need to use then when returning promises.
getData(value, type) {
let urls = [
'https://wind-bow.gomix.me/twitch-api/streams/' + value,
'https://wind-bow.gomix.me/twitch-api/users/' + value
];
const getJson = url => fetch(url).then(res => res.json());
Promise.all(urls.map(getJson))
.then(streamer => {
if (type === "search") {
this.setState({ streamer });
console.log("searching")
} else {
console.log("displaying");
this.getStreamer(streamer[0], streamer[1]);
}
}).catch(err => {
console.log('Something went wrong...')
})
}
I have three methods (each is a promise) that does SELECT from the database.
getDeliverDate()
.then(calculateOrderList)
.then(getOrderItemsForOrder)
For each deliverDate, I need to get the corresponding list of orders, and for each order I need to get the list of items. I will then build a JSONview to send to the client. To do that, I think I need to wrap the code above with a for loop, and presumably have a "global" object made of arrays etc.. and have to push to the object data from each method. I am not really sure if the approach will work. Can someone please tell me how to get it to work using the code above as an example.
Push all the promises into an array then use Promise.all to wait for all promises to finish and return the result. Something like
var promises = []
for (...) {
promises.push(getDeliverDate()
.then(calculateOrderList)
.then(getOrderItemsForOrder));
}
return Promise.all(promises);
Edit, all not when -- got my promise libraries confused
Better way to do that is use Promise.all:
Promise.all([getDeliverDate, calculateOrderList, getOrderItemsForOrder])
.then(values => {
console.log(values);
});
If what I understand is correct (as given in comments):
getDeliverDate()
// get array of delivery dates
.then((deliveryDates = []) => {
// for each delivery date, I need to get corresponding list of orders
const promises = deliveryDates.map(date => calculateOrderList(date));
return Promise.all(promises);
})
// get order list as an array
.then((orderList = []) => {
// for each order I need to get list of items corresponding to that order
const promises = orderList.map(order => getOrderItemsForOrder(order));
return Promise.all(promises);
})
// get item list as an array
.then((items) => console.log('got everything : ', items))
.catch((error) => console.log('error : ', error))
Looks like you need a lot of API calls. Probably we should think about optimizing backend.
I'm struggling with the following: So i got a list of ids in a user object, i would like to retrieve the list of users, whose those ids belong to. My idea was to use a map to convert the array of ids to an array of users, I came to the obvious wall. since the call is asynchronous y can't expect the users to be there, however yes the promise.
Is there anyway to return this promises in a way that Ember can show the data when they get resolved ? I don't really care when they get resolved. but when they do, that they render the data.
What is happening now is that i get a list of Promises, which is fine, and kind of expected, but how do i tell ember, ok when you do resolve the promises show the data?
Thanks in advance
let users = this.get('user.followingIds').map((followerId) => {
return this.store.findRecord('user', followerId).then((user) => {
console.log('resolved follower ', user.get('name'));
return user;
}).catch((e) => {
console.error('user catch', e);
});
});
this.set('followers', users);
The console log output is
resolved follower james stuart
on onother filter i have this
this.store.query('followers', {}).then((followers) => {
this.set('followers', followers);
}).catch((e) => {
console.error('publisher catch', e);
});
and that works as expected, but its not in a map, this is just to show im displaying the results the right way
Thank u Daniel for the help, i ended up changing the map for a forEach and populating the array
this.get('user.following').forEach((followerId)=>
{
this.store.findRecord('user', followerId)
.then((user) => {
console.log('resolved follower ',user.get('name'));
publishers.pushObject(user._internalModel);
})
.catch((e) => {
console.error('publisher catch', e);
});
});
I had to put the _internalObject thing otherways it wouldn't work took that from here
Dynamically add js object to model array in 1.13