Make request inside a map function in ember 2 - javascript

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

Related

JavaScript the rest of function executes before API calls

I have a problem with a simple function which where I want to call an API and then do something with the response. Basically, I just want to set my react component state to the response I get and then navigate to the other page The problem is that my code executes another part of the function before an API call is finished, and I end up on another page with console.log of undefined
There is my function:
const startNewGame = () => {
GameService.startGame()
.then((response) => {
setGame(response.data);
console.log(game);
navigate('intro');
})
.catch((e) => {
console.log(e);
});
};
I can wrap my navigate into if(!game !== undefined) but then I have to click two or more times on a button.
Thank you all guys for help :)
You probably do several things incorrect at the same time, so to understand what exactly is wrong might take some time. Take these steps to debug your code:
Make each .then call do only one thing (and stick to that principle in other cases). You could chain as many .then as you like. Moreover you could return data from one .then to the next, so your code might look like this:
GameService.startGame()
.then(response => response.data)
.then(data => {
setGame(data)
})
.then(() => {
console.log(game);
navigate('intro');
})
.catch((e) => {
console.log(e);
});
Understand your components composition. Where exactly are you saving your response? is it just local component useState or some Context Api state that wraps the app? When you navigate to "other page" your "current page" state will be unavailable to "other page" unless you keep the data somewhere up in the tree when both pages could access that.
For further references keep in mind that setGame is asynchronous, so you need to wait for the state to be updated to make sure that its updated.
Try this:
const startNewGame = () => {
GameService.startGame()
.then((response) => {
setGame(response.data);
// game is not updated yet
// console.log(game); <- Remove this line
// navigate('intro'); <- Remove this line
})
.catch((e) => {
console.log(e);
});
};
useEffect(()=>{
if(game !== undefined){
navigate('intro')
}
}, [game])

How to chain my promises - Fetch not returning desired results

Fetch Promises Not Working For Me
I am a newbie when it comes to using Javascript Promises. In my current project, I believe Promises are a candidate for the task I am trying to achieve. The project is simple, it is an online form to submit a quote (or estimate) to a customer.
I am working on the page that will display a Quote that has already been submitted - ( view-quote.html )
Here is the task broken down:
Given a quote_id (url param), I want to query the QUOTES table.
In those results are a customer id.
Finally, I want to query the ITEMS table using the quote_id.
Synchronous or Asynchronous ?
Since one query depends upon another, I thought I could use the Fetch statement, which is "then-able".
I THINK I am supposed to use asynchronous code to achieve this task, right? I'm not sure though. Maybe traditional "callbacks" are what I need?
My Current Non-Working Code...
Here is as far as I got. I pieced this together by following tips and tutorials I found on Stack's site.
var getQuote = function() {
fetch(apiQuoteUrl+"GL555") // for testing, I hardcoded a quote num
.then(status)
.then(json)
.then(function(data) {
// WORKS - this DOES return me the client id
//alert(data[0].client_id);
gClient_id = data[0].client_id; // move to global var
}).catch(function(error) {
console.log('Request failed', error);
});
};
// This function takes one parameter, the client id
// which comes from the fetch call above.
var getClient = function(clientId) {
fetch()
.then(status)
.then(json)
.then(function(data) {
// TO BE DETERMINED, NOT SURE
// WHAT TO PUT HERE
}).catch(function(error) {
console.log('Request failed', error);
});
};
var getItems = function() {
fetch()
.then(status)
.then(json)
.then(function(data) {
// TO BE DETERMINED, NOT SURE
// WHAT TO PUT HERE
}).catch(function(error) {
console.log('Request failed', error);
});
};
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
What to do next?
Ok, I have the framework put in place. But, I don't know to proceed. I have followed dozens of tutorials on Fetch and Promises, but they don't quite fit my needs, therefore, I am stil stuck.
Right Track?
So I am now concerned that I am making this harder than it needs to be. Am I even on the right track by using promises?
Thank you for looking. Your advice/code help is really appreciated.
John
They weren't working for me either!
Hello! I believe I recently had the same problem as you: "Chaining Promises"
A quick search brought me here, and I was able to resolve my problems.
The basics are, you need to return a value from a promise in order to .then() it.
So in the case of fetch() try something like this
var getQuote = function() {
fetch(apiQuoteUrl + "GL555")
.then(status => return status.json())
.then(data => {
alert(data[0].client_id);
gClient_id = data[0].client_id;
}).catch(error => {
console.log('Request failed', error);
});
};

why my javascript its use to long time to run?

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.

Promise.all() with map, silenced

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 ?

for loop and promises

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.

Categories