I have array of customers and addresses endpoint URL as below
customerArray = [
{name:customer1, id: 1, address: {streetName: '123 lane'}},
{name:customer2, id: 2, address: {streetName: 'xyz lane'}},
{name:customer3, id: 3, address: {streetName: 'abc lane'}}
]
URL = 'id/addresses'
GET request for URL will return array of addresses based on customer ID
if we get empty array as response then we need to add address from "customerArray" for that id
// This is what I am doing to meet the requirement - seems this is not the right approach. Please help me to fix this
customerArray.forEach((customer) => {
const getObj = {
url: `${customer.id}/addresses`,
method: GET
};
axios(getObj)
.then((getResult) => {
if (getResult.length === 0) {
const postObj = {
url: `${customer.id}/addresses`,
method: POST,
data: customer.address
};
axios(postObj)
.then((postResult) => {
// I am not sure what to do here - I leaving blank so iteration will continue
})
.catch((err) => {
res.status(400).json(err);
});
}
})
.catch((err) => {
res.status(400).json(err);
});
});
Please help me to fix it
I think you don't know how to get the final data. Basically, you should put your promises into an array and you Promise.all to wait for all of them to finish.
Please comment if something wrong. Hope this helps
const promises = customerArray.map((customer) => {
const getObj = {
url: `${customer.id}/addresses`,
method: GET
};
return axios(getObj)
.then((getResult) => {
if (getResult.length === 0) {
return {
url: `${customer.id}/addresses`,
method: POST,
data: customer.address
};
}
return null;
})
.then((postObj) => {
if (postObj) {
return axios(postObj)
}
return null
})
});
Promise.all(promises)
.then(result => {
// the result is a list of data from axios(postObj)
console.log(result);
res.json(result);
})
.catch((err) => {
res.status(400).json(err);
});
Related
this is my problem: I need to make some fetch POST requests to my server. The server holds a list of names. Each name corresponds to a list of elements which I need to browse, in order to find a specific element from all the lists.
I have to work with this structure, can't change it.
My approach was to write a fetch request, to get the all these names (of the lists I need to browse), then I would loop through each name and fetch to get the according lists from the server. Once I get these lists I can loop through the elements till I find the correct element.
This is not an easy task for me as I am new to javascript.
This is how I implemented this:
function browse(){
fetch(TARGET_IP, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-Auth-Token": AUTH_TOKEN
},
body: JSON.stringify({
"id": messageId++,
"jsonrpc": "2.0",
"method": "Browse",
"params": {
"mode": "children"
}
})
})
.then(response => response.json())
.then((data) => {
data.results = Object.assign(Array.prototype, data.result);
data.results.forEach(element => {
if (element.datatype == "datablock") {
datablocks.push(element.name)
}
})
return datablocks;
})
.then((datablocks) => {
datablocks.forEach(element => {
browseDatablocks(element)
})
})
.catch(e => console.error(e))
}
function browseDatablocks(dbname) {
fetch(TARGET_IP, {
method: "POST",
headers: {
"Content-type": "application/json",
"X-Auth-Token": AUTH_TOKEN
},
body: JSON.stringify({
"id": messageId++,
"jsonrpc": "2.0",
"method": "Browse",
"params": {
"var": "\"" + dbname + "\"",
"mode": "children"
}
})
})
.then(response => response.json())
.then((data) => {
data.results = Object.assign(Array.prototype, data.result);
data.results.forEach(element => {
if (element.name == "P_Index")
{
console.warn(dbname);
// This is the element I need and would save it
}
})
})
.catch(e => console.error(e))
}
Now all sorts of strange things happen with this approach.
The console outputs elements that are just not the elements I search for, which is just wrong as I checked on server side.
Some requests are not even handled.
I assume these problems occur because I send too many requests at the same time (the nested ones in browseDatablocks).
How can I handle one request and then the next one? Or are there other ways to implement this?
Thanks.
looks like what you need is Promise.all.
if i understand the problem correctly:
first return the fetch result in function browseDatablocks(dbname)
...
function browseDatablocks(dbname) {
return fetch(TARGET_IP, {
....
And return the value, in last then
.then((data) => {
data.results = Object.assign(Array.prototype, data.result);
const filtered = data.results.filter((element) => element.name == "P_Index");
return filtered;
});
Then in function browse(), last then:
.then((datablocks) => {
const results = datablocks.map(element => browseDatablocks(element));
return Promise.all(results);
})
.then((listOfResults) => {
// Some magic here
})
// Edit or to do them in order:
In function browseDatablocks(dbname), last then:
do the handling, and return a bool instead of filtered eg true = all done, false fetch the next. Something like:
.then((data) => {
data.results = Object.assign(Array.prototype, data.result);
const found = data.results.find(element => element.name == "P_Index");
if (found) {
// Some handling
return true;
}
return false;
})
And in function browse(), last then
.then(async (datablocks) => {
let i = 0;
while(i < datablocks.length) {
const handled = await browseDatablocks(datablocks[i]);
if (handled === true) {
break;
}
i += 1;
}
});
I'm new to javascript and there's a problem I'm not all able to solve.
I have one array of objects, which contains 2 attributes. I want to connect the attributes, one of which will be a key and the other will be a value.
this is what I have:
[{"prefer":"code_html","rating":"5"},{"prefer":"code_css","rating":"3"}]
This is what I want to get:
[
{
"code_html": "5"
},
{
"code_css": "3"
}
]
I run this function:
const array = [{"prefer":"code_html","rating":"5"},{"prefer":"code_css","rating":"3"}]
const result = array.map(({prefer, rating}) => ({[prefer]: rating}));
console.log(result);
But I can not understand why it does not work for me.
This is the print I get, I do not understand what is wrong
[{},{},{}]
I use this code in nodeJs, maybe that's why I have a problem:
exports.addUserKmeansMatchVer2 = (req, res) => {
console.log("addUserKmeansMatch function filter:");
arr = [];
if(req.query.filterArray)
{
arr = [...req.query.filterArray];
console.log("line 256" + typeof(req.query.filterArray));
//this is print line 256object
console.log("line 257" +arr);
//this is works prints: line 257{"prefer":"sport_swimming","rating":"3"},{"prefer":"code_html","rating":"5"},{"prefer":"code_css","rating":"3"}
console.log("line 258" + req.query.filterArray);
//print exactly the same as line 257
}
let onlyPreferencesAllow = [];
arr.forEach(({prefer,rating}) => onlyPreferencesAllow.push({[prefer]: rating}));
console.log("line 262" + JSON.stringify(onlyPreferencesAllow));
//this is NOT work prints: line 262[{},{},{}]
db.doc(`/match/${req.user.handle}`)
.set("testing")
.then(() => {
return res.json({ message: "Details added successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
}
})
})
};
I noticed that in line 257 it prints for me without the parentheses of the array without [], but in line 262 it prints with the parentheses [], I do not quite understand it
I thought of something I forgot to mention,
I get the req.query.filterArray, through the params.
Here's how I do it:
export const makeMatchVer2 = (data) => (dispatch) => {
dispatch({ type: LOADING_DATA });
axios
.get('/kmeansFilter', {
params: {
filterArray: data
}
})
.then((res) => {
dispatch({
type: MAKE_MATCH,
payload: res.data
});
})
.catch((err) => {
dispatch({
type: MAKE_MATCH,
payload: []
});
});
};
the data itself is an array, maybe here i do the mistake
The solution that worked for me:
When I send an array in params to api, I need to use JSON.stringify.
export const makeMatchVer2 = (data) => (dispatch) => {
dispatch({ type: LOADING_DATA });
axios
.get('/kmeansFilter', {
params: {
filterArray: JSON.stringify(data)
}
})
.then((res) => {
dispatch({
type: MAKE_MATCH,
payload: res.data
});
})
.catch((err) => {
dispatch({
type: MAKE_MATCH,
payload: []
});
});
};
And when I get the answer in nodeJS, I have to use JSON.parse
exports.addUserKmeansMatchVer2 = (req, res) => {
console.log("addUserKmeansMatch function filter:");
arr = [];
if(req.query.filterArray)
{
arr = JSON.parse(req.query.filterArray);
}
let onlyPreferencesAllow = [];
arr.forEach(({prefer,rating}) => onlyPreferencesAllow.push({[prefer]: rating}));
console.log("line 262" + JSON.stringify(onlyPreferencesAllow));
db.doc(`/match/${req.user.handle}`)
.set("testing")
.then(() => {
return res.json({ message: "Details added successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
}
})
})
};
I have a list of posts containing userId. When fetching n no.of post, I want to loop throught and get and fetch user data and append them into the post.
But before the loop gets resolved, the function gets return with undefined. After that, the post data gets listed but I want the post data to be fetched first.
I am new to promises and async. If there are any other solutions that I can use, then please notify me.
I am using sailsjs.
fetchPosts: async (req, res) => {
let feeds = [];
posts = await Posts.find({
skip: offset,
limit: limit,
sort: sort,
});
if (posts) {
/**
* LOOPING THROUGH FETCHED POST LOOP TO GET
* USER DATA, LIKE, SHARE, FOLLOW, BOOKMARKS
*/
const functionWithPromise = (post) => {
//a function that returns a promise
console.log(feeds);
return Promise.resolve(post);
};
const anotherAsyncFunction = async (post) => {
return functionWithPromise(post);
};
const getUser = async (userId, post) => {
return new Promise(async (resolve, reject) => {
const user = await Account.findOne({ id: userId });
if (user) {
post = {
...post,
user: {
id: user.id,
uName: user.uName,
provider: user.provider,
dpURL: user.dpURL,
provider: user.provider,
},
};
resolve(post);
} else {
reject(null);
}
});
};
const anAsyncFunction = async (post) => {
if (post.isAdminPost) {
post = {
...post,
user: {
id: "5f3b8bf00dc3f12414b7f773", // this is usedid of admin#dopaminetalks.com in `Admin` model
uName: "DTOfficial",
provider: "LOCAL",
dpURL: "/dpURL/86a73b80-babc-4caa-a84c-762f6e9c1b36.png",
},
};
feeds = [...feeds, post];
return anotherAsyncFunction(feeds);
} else {
getUser(post.userId, post).then((post) => {
feeds = [...feeds, post];
return anotherAsyncFunction(feeds);
});
}
};
const getData = async () => {
return Promise.all(posts.map((post) => anAsyncFunction(post)));
};
getData().then((data) => {
console.log(data);
return res.json({
status: true,
msg: "Posts Fetched",
data: data,
});
});
}
},
The update is not working, but the promise is returning success. I think it may be with the Where in the sequelize query not finding the value from the array of objects productsCodeArr.
const orderid = req.params.orderid
const productsCodeArr = convertedInputs.map(code => {
return ({
id: code.id,
picked: code.picked,
notPicked: code.notPicked
});
})
if(productsCodeArr) {
db.Detallepedido.update({
pickeado: productsCodeArr.picked,
nopickeado: productsCodeArr.notPicked
},
{
where: {
pedido_id: orderid,
producto_id: productsCodeArr.id
}
})
.then(() => {
console.log('Success!');
}})
.catch(reason => {
console.log(reason);
})
I did it!
I used Promise.all with a map of the array.
Promise.all(productsCodeArr.map(object=>{
return db.Detallepedido.update({
pickeado: object.picked,
nopickeado: object.notPicked
},
{
where: {
pedido_id: orderid,
producto_id: object.id
}
})}))
I believe my promises aren't being finished because I'm not handling them correctly. At the end of my code, within Promise.all(), console.log(payload) is displaying {}. When it should display something like this:
{
project1: {
description: '...',
stats: {python: 50, css: 50}
},
project2: {
description: '...',
stats: {python: 25, css: 75}
},
project3: {
description: '...',
stats: {python: 10, css: 90}
}
}
code:
app.get("/github", (req, res) => {
const authorizationHeader = {headers: {Authorization: 'Basic ' + keys.github.accessToken}};
const user = 'liondancer';
const githubEndpoint = 'api.github.com/repos/';
var payload = {};
let promises = req.query.projects.map(project => {
let datum = {};
const githubAPIUrl = path.join(githubEndpoint, user, project);
return fetch('https://' + githubAPIUrl + '/languages', authorizationHeader).then(res => {
// Get Languages of a project
if (!isStatus2XX(res)) {
throw 'Status code not 2XX:' + res.status;
}
return res.json();
}).then(res => {
let languagePercentages = {};
let total = 0;
// get total
Object.keys(res).forEach(key => {
total += Number.parseInt(res[key]);
});
// compute percentages
Object.keys(res).forEach(key => {
languagePercentages[key] = (Number.parseInt(res[key]) / total * 100).toFixed(1);
});
datum.stats = languagePercentages;
// Get description of a project
fetch('https://' + githubAPIUrl).then(res => {
if (!isStatus2XX(res)) {
throw 'Status code not 2XX: ' + res.status;
}
return res.json();
}).then(res => {
datum.description = res.description;
payload[project] = datum;
});
}).catch(err => {
console.log('Github API error: ' + err);
});
});
Promise.all(promises).then(() => {
console.log(payload);
res.send(payload);
}).catch(err => {
console.log('nothing ever works...: ' + err);
});
});
At first I replaced .map with .forEach() to have the code execute and the code seemed to have worked properly. payload had the values I expected. However, now that I want to send the aggregated results, I cant seem the properly execute the promises in the correct order or if at all.
just change this line
fetch('https://' + githubAPIUrl).then(res => {
into this
return fetch('https://' + githubAPIUrl).then(res => {
so promise.all will resolve after all nested promises have resolved so payload filled up.