So I am trying to do a POST request in Angular from an array. Basically, when a user selects multiple items in a list they can "unlock" each item. So the issue I am running into is how to do a POST with a forEach. I was able to do a POST with a forLoop but the issue is that when it does one POST it does not do the other one. Can someone please point out what I am doing wrong or if there is a better solution to this problem?
Here are the other Stack questions I looked through to find a possible solution:
Http request in forEach function. Angular2
Angular http post on loops
Chaining http calls in angular 2 in a for loop
component.ts
locked: Array<any> = [];
// Unlock
unlock() {
let observer = {
next(data) {
data => console.log(data)
},
error(error) {
return new Error('Post Error');
},
complete() {
console.log("Completed");
// window.location.reload();
}
}
// On unlock send lock data to Service for POST
this.http.postUnlock(this.unlocked).subscribe(observer);
}
service.ts
// POST to UNLOCK RESOURCES
postUnlock(locked) {
let headers = new Headers();
headers.append( 'Content-Type', 'application/json');
headers.append('Access-Control-Allow-Origin', '*');
locked.forEach((lock) => {
let newBody = JSON.stringify(lock);
let auth = lock.AuthID;
let form = lock.FormName;
let options = new RequestOptions({ headers: headers, method: 'post', body: newBody });
let newUrl = this.url + `?authid=${auth}&formname=${form}`;
// POST to URL
return this.http.post(newUrl, options).map(res => res.json());
});
}
Is it something that has to do with the Observable or is this something that can be handled with Promises?
Thank you for your help.
here is a mix between what you looked for (Http request in forEach function. Angular2) and your code.
you cannot return a value from a for each it will exits the function (What does `return` keyword mean inside `forEach` function?)
hope it helps
postUnlock(locked){
//create an array of Observables
let allQueries = locked.map(lock => {
let newBody = JSON.stringify(lock);
let auth = lock.AuthID;
let form = lock.FormName;
let options = new RequestOptions({ headers: headers, method: 'post', body: newBody });
let newUrl = this.url + `?authid=${auth}&formname=${form}`;
// POST to URL
return this.http.post(newUrl, options).map(res => res.json());
});
//return a new observable that will emit all the http results
return Observable.forkJoin(allQueries)
}
Related
I'm currently trying to make a "Code by Zapier" action for making API requests to IronWifi in order to create a user and fill it with information/details.
Currently I've been able to do this with four "Code by Zapier" actions. Each action is one fetch request.
However, I was looking to combine all four API requests into one action. It seems that when a fetch request is used that a 'callback' must be used right after. And I believe that this forces the action to stop at that moment.
Currently I've tried to write code for creating the user and then adding a first name. The code I have so far is as follows:
var headers = {
"Authorization": "Bearer 22ef59a2eb2a6939f5bd26bb43ff8b2d4d9b24ab",
"Content-Type": "application/json"
};
var url = "https://us-east1.ironwifi.com/api/users";
var username = inputData.name;
var data = JSON.stringify({"username":username});
//First fetch request (API hit) for creating a user in IronWifi
var user = fetch(url, {method: "POST", headers: headers, body: data}).then(function(binaryResponse) {
return binaryResponse.json();
}).then(function(jsonResponse) {
callback(null, {result: jsonResponse.id});
}).catch(callback);
url = url + "/" + user.result;
var firstName = inputData.first
data = JSON.stringify({"firstname":firstName});
//Second fetch request (API hit) for giving the user a first name
var nameFirst = fetch(url, {method: "PATCH", headers: headers, body: data}).then(function(binaryResponse) {
return binaryResponse.json();
}).then(function(jsonResponse) {
callback(null, {result: JSON.stringify(jsonResponse)});
}).catch(callback);
var output = {user: user, firstname: nameFirst};
return output;
It seems though that the second fetch request is never being executed but the first fetch request is being executed. Would there be a way to have these fetch requests execute successfully in a sequential order?
The source of your confusion here is that you're using a very old style of existing an asynchronous function. When callback is run, then the function exits and your second requests is never called. Instead, you should use await, a better way to write asynchronous JS code.
callback is still mentioned in the Zapier docs, but it also notes that await is available (see here).
Try something like this:
const headers = {
Authorization: "Bearer 22ef59a2eb2a6939f5bd26bb43ff8b2d4d9b24ab",
"Content-Type": "application/json",
};
const url = "https://us-east1.ironwifi.com/api/users";
// User request setup
const username = inputData.name;
const userBody = JSON.stringify({ username: username });
// First fetch request (API hit) for creating a user in IronWifi
const userResponse = await fetch(url, {
method: "POST",
headers,
body: userBody,
});
const userData = await userResponse.json();
// do error checking?
// Name request setup
const nameUrl = `${url}/${userData.id.result}`; // double check .id.result
const firstname = inputData.first;
const nameBody = JSON.stringify({ firstname });
// Second fetch request (API hit) for giving the user a first name
const nameResponse = await fetch(url, {
method: "PATCH",
headers,
body: nameBody,
});
const nameData = await nameResponse.json();
// do error checking?
return { user, firstname };
That code probably won't work right out of the box - I have no idea what the actual responses look like. But, it should get you moving in the right direction.
Separately, you should reset your API key (22ef59...) and audit any usage of it. If it was a valid token, anyone that read this question will have been able to use it.
New to NodeJS and JavaScript
I am using NodeJS to make an API call to return some JSON data within an async function. Presently, the API call is working as intended and I have parsed the data that I am looking for. The trouble I am having is using that parsed json data as a condition within an IF statement so I can continue along with the rest of the scripts intended functions. To simplify for the mean time I have written it to display a string statement if the JSON data is what I expect it to be:
const fetch = require("node-fetch");
var accessToken = "Bearer <ACCESS TOKEN>";
var url = '<API ENDPOINT>';
var headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': accessToken
};
const getData = async url => {
try {
const response = await fetch(url, {method: "Get", headers: headers});
const json = await response.json();
console.log(json.status);
return json.status
} catch (error) {
console.log(error);
}
};
let apiStatus = getData(url);
let activated = "ACTIVATED";
let configured = "CONFIGURED";
if (apiStatus.toString() !== activated) {
console.log("BLAH");
}
Essentially, if the return value of "json.status" is equal to "ACTIVATED", then I will perform an action. Else, I will perform a different action.
At present, I am unable to use the output of the "getData()" to be used in an IF condition. Any assistance with next steps would be appreciated.
You need to wait for the promise to be resolved, because right now you'd be evaluating a Promise (pending) object.
Your getData() function is fine.
let apiStatus = await getData(url);
I don't think async works on the window scope, you can try this out. If this doesn't work, then you just need to wait for the promise to be resolved.
getData(url).then(
status => {
if (status.toString() === 'activated'){
...
}
});
Im trying to fetch subcategories from my mvc application with reference to the category id with async fetch
I already fetched the categories and its all working
but when i try to fetch the subcategories with a post request it doesn't work!
//SubCategories
const categoriesLiList = document.querySelectorAll('.btn');
const getSubCategories = async () => {
const liBtnClick = list => {
nodeListForEach(list, cur => {
cur.addEventListener('click', () => {
debugger;
let categoryId = cur.value;
console.log(categoryId);
const getSubCategoriesById = async (url = ``, data = {}) => {
const subsResult = await fetch(url, {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json"
},
redirect: "follow",
referrer: "no-referrer",
body: JSON.stringify(data)
});
const subsData = await subsResult.json();
const populateSubCategories = arr => {
arr.forEach(cur => {
const subCategoriesLi = `
<li>${cur.Name}</li>
`;
document.querySelector('#subcategories').insertAdjacentHTML('beforeend', subCategoriesLi);
});
};
populateSubCategories(subsData);
};
getSubCategoriesById(`/controllername/jsonresult/ID`, { ID: categoryId });
});
});
};
liBtnClick(categoriesLiList);
};
getSubCategories();
The result should be the data from the api but its not reading the ID param.
what should i change in my post request??
EDIT: I am such an idiot lol my api wasn't working correctly, so for future purposes always test your apis with postman :)
also, there's no need for a post request! just a normal fetch get reques:
await fetch(`/controllerName/JsonResult/${categoryId}`);
I am such an idiot lol
my api wasn't working correctly, so for future purposes always test your apis with postman :)
also, there's no need for a post request! just a normal fetch get reques:
await fetch(`/controllerName/JsonResult/${categoryId}`);
I try to get a fresh list of data by invoking a url using fetch. This url return a json. Following the instructions described in these links fetch(), how do you make a non-cached request? and https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/, I build the following init object.
const headers = new Headers();
headers.append('pragma', 'no-cache');
headers.append('cache-control', 'no-cache');
const init = {
method: 'GET',
headers: headers,
cache: 'reload',
};
But after adding it as a second argument to fetch method the return data does not include the most recently added data, so I think it is due to cache.
The complete example is as follows
function getYears() {
const id = getId();
const request = new Request(`index.php?ep=name&id=${id}`);
const headers = new Headers();
headers.append('pragma', 'no-cache');
headers.append('cache-control', 'no-cache');
const init = {
method: 'GET',
headers: headers,
cache: 'reload',
};
fetch(request, init)
.then(response => response.json())
.then(json => {
window.yearCollection = years;
})
.catch(error => {
console.log(error.message);
});
}
The logical flow is the following, when loading the page the method getYears () is invoked, then when sending data in a form, the page is reloaded. Here the list of years is not updated, I must refresh the page manually, to get the list with the updated data
In my Angular application service I have a method that makes a call to a mock JSON:
my.service.ts:
...
private baseUrl: string = 'http://localhost:9999/accounts-grid.json';
...
loadAccounts() {
if (this.dataStore.responseObject) {
this.refreshDataStore();
}
let token = this.authenticationService.getToken();
let headers = new Headers({ 'netx.esf.AuthenticationService': token });
let options = new RequestOptions({ headers: headers });
this.http.get(`${this.baseUrl}/positions/priorday/${accountNumber}`, options)
this.http.get(`${this.baseUrl}`, options)
.map((response: Response) => response.json())
.subscribe(
...
error => {
this.logService.error('loadAccountList() exception:', error);
this.setError(this.message[0], error._body); });
return this.responseObject$;
}
I would like to be able to load a different dummy JSON with the same call depending how many times the method was called. For example, the first time I call loadAccounts(), I would like to get a response from accounts-grid.json, the second time I make this call I would like to get a response from, say, accounts2-grid.json.
Is this possible?
Add a local variable to the service to keep track:
...
private baseUrl: string = 'http://localhost:9999/accounts-grid.json';
private callCount = 0;
...
loadAccounts() {
if ( this.callCount > 0 ) { const newUrl = this.baseUrl.substring(0, this.baseUrl.lastIndexOf('.json')) + this.callCount.toString() + this.baseUrl.substring(this.baseUrl.lastIndexOf('.json')); }
this.callCount += 1;
if (this.dataStore.responseObject) {
this.refreshDataStore();
}
let token = this.authenticationService.getToken();
let headers = new Headers({ 'netx.esf.AuthenticationService': token });
let options = new RequestOptions({ headers: headers });
this.http.get(`${newUrl}/positions/priorday/${accountNumber}`, options)
this.http.get(`${newUrl}`, options)
.map((response: Response) => response.json())
.subscribe(
...
error => {
this.logService.error('loadAccountList() exception:', error);
this.setError(this.message[0], error._body); });
return this.responseObject$;
}
You will probably also want to take care of the callCount item to subtract a count if there's an error, but this is the general idea.