How to pass optional parameters using fetch vanilla JS - javascript

I'm using JavaScript fetch GET method to call an API. The API returns data; however, there are optional parameters I'd like to pass in to format the data response in a different way. How do you pass optional parameters using the fetch method?
async function getText(){
let passageParam = randomPassage();
//API credit
let Url = 'https://api.esv.org/v3/passage/text?q=' + passageParam + params;
console.log(Url);
//Await - Used with Async
//Suspend function exeeuction until the Async promise settles and returns its result
let response = await fetch(Url, {
method: 'GET',
headers: {
'Authorization': 'myToken'
},
params = {
'indent-poetry': False,
'include-headings': False,
'include-footnotes': False,
'include-verse-numbers': False,
'include-short-copyright': False,
'include-passage-references': False
}
});
if(response.ok){ // if HTTP-status is 200-299
// get the response body
let passage = await response.json();
populateUI(passageParam, passage.passages[0]);
//console.log(passage);
} else{
alert("HTTP-Error: " + response.status);
}
//Function to input json response to HTML
function populateUI(ref, verse){
//strip verse
document.getElementById('reference').innerHTML = ref;
document.getElementById('verse').innerHTML = verse;
}
}

When using fetch with GET, it's generally expecting parameters be sent via a Query String.
You can try something like this:
let passageParam = randomPassage();
let extraParams = '&indent-poetry=False&include-headings=False' +
'&include-footnotes=False&include-verse-numbers=False' +
'&include-short-copyright=False&include-passage-references=False';
let Url = 'https://api.esv.org/v3/passage/text?q=' + passageParam + extraParams;
console.log(Url);
Alternatively you can do something like this:
let passageParam = randomPassage();
let extraParams = {
'indent-poetry': 'False',
'include-headings': 'False',
'include-footnotes': 'False',
'include-verse-numbers': 'False',
'include-short-copyright': 'False',
'include-passage-references': 'False'
}
let Url = 'https://api.esv.org/v3/passage/text?q=' + passageParam +
'&' + (new URLSearchParams(extraParams)).toString();
console.log(Url);
And also delete the params expression.

Since you are making a GET request to a URL-EndPoint using fetch. The URL-EndPint will always return the same data format every time you call it.
And formatting a response is not in our hands in this case. To check all the response details, go to the network tab of Developer Console (do Ctrl+Shift+I), you can see the response headers and other related stuff that you have received in the response and see if any information is useful to you there itself.

Related

Async function must return a boolean value

I have a method that I am calling on the onsubmit event in the form tag.
So I need a true or false to be returned from the method.
I use an API to retrieve data, and according to the response from the API, I return true or false. But because it is an async function thats running, I cant get it right to wait for the response from the API, analyze it and then return my decision.
Any ideas on how I could solve this problem
function GetPolygonID()
{
document.getElementById("displayerror").innerHTML = "";
var retrievedpoly = document.getElementById('polygondetails').value;
var parts = retrievedpoly.split('coordinates');
var parttoadd = parts[1].substring(0, parts[1].length - 2) + "}";
console.log(parttoadd);
var myx = '{"name":"Polygon OneTwoThree","geo_json":{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates' + parttoadd;
var url = 'http://api.agromonitoring.com/agro/1.0/polygons?appid=apiid';
const request = async() => {
const response = await fetchPoly(url, myx);
const data = await response.json();
const errorCheck = await CheckInfo(data);
console.log("2: " + errorCheck);
return await errorCheck;
};
return request();
}
function CheckInfo(data)
{
let flag = false;
console.log(data);
if (JSON.stringify(data).includes("Geo json Area is invalid. Available range: 1 - 3000 ha"))
{
var myval = JSON.stringify(data);
//myval = myval.replace(/\\n/g,"<br/>");
parts = myval.split("\\n ").join(",").split("\\n");
console.log(parts);
var todisplay = parts[1].substring(10);
todisplay += ("<br/>" + parts[2].substring(10).replace(",", "<br/>").replace("c", "C"));
console.log(todisplay);
document.getElementById("displayerror").innerHTML = todisplay;
} else
{
flag = true;
}
console.log("1:" + flag);
return flag;
}
function fetchPoly(url, data)
{
return fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, cors, *same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json"
// "Content-Type": "application/x-www-form-urlencoded",
},
redirect: "follow", // manual, *follow, error
referrer: "no-referrer", // no-referrer, *client
body: data // body data type must match "Content-Type" header
});
}
I did try it with .then(), originally, then I broke it down like this, as I thought it would be easier to return a value here.
Essentially I need GetPolygonID() to return a boolean which it gets from CheckInfo(). CheckInfo() determines if the form should submit or not
Any thought on how I could fix this?
Thank You
GetPolygonID() function returns a Promise, so it must be either called with await or you can call then upon it:
var res = await GetPolygonID();
GetPolygonID().then(res => console.log(res));
You can make the whole function async:
async function GetPolygonID() {
document.getElementById("displayerror").innerHTML = "";
var retrievedpoly = document.getElementById('polygondetails').value;
var parts = retrievedpoly.split('coordinates');
var parttoadd = parts[1].substring(0, parts[1].length - 2) + "}";
console.log(parttoadd);
var myx = '{"name":"Polygon OneTwoThree","geo_json":{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates' + parttoadd;
var url = 'http://api.agromonitoring.com/agro/1.0/polygons?appid=apiid';
const response = await fetchPoly(url, myx);
const data = response.json();
const errorCheck = CheckInfo(data);
console.log("2: " + errorCheck);
return errorCheck;
}
Using an async function for a form validation, you can do this:
function onSubmit(form) {
GetPolygonID().then(res => res ? form.submit() : null);
return false;
}
...
<form method="POST" onsubmit="return onSubmit(this);">
...
I have used two ways for returning boolean from the async function as we all know when we use keyword async in functions then it will return a Promise, but what if we want boolean values simple true or false then we can use two ways for that.
By using anonymous function with async and await
const Abc=async ()=>{
return false
}
(async () => {
try{
console.log(await Abc())
}catch(e){
console.error(e)
}
})();
Another way is simply use then() catch()
Abc().then(res=>console.log(res)).catch(e=>console.error(e))

Returning array after being filled in async function - Node.js

I want to access some data from an API and ran into a problem. My code is fetching some data from the API, will compare it with a local copy of an API. I want it to store some data in an array if the local copy does not match the copy fetched from the API. The fetching and comparison is working fine. The problem comes up when I try to fill the array and want to give it back. The request function is async so my return value at the end will be undefined. My function checkForDiff should return this array after the for-loop is done, because after the foor-loop the array should be filled with the information I need. I am a newbie in Nodejs so I really do not know how to fix it. I need the array to be filled before returning it, but the async request call is causing me problems. How can I achieve this kind of behavior?
Thank you for your help in advance
function checkForDiff(){
let outdatedLanguages = [];
var options = {
url: 'https://xxxxxxxxxxxxxxxxxxxxxxxxx',
headers: {'Key': 'xxxxxxxxxxxxxxxxxxxxxx'}
};
for(let index = 0; index < locales.length; index++){
//Change url for new https request
options.url = `https://xxxxxxx?locale=${locales[index].symbol}`
//Send new https request to API
request(options, (error, response, body)=>{
var localState = hash(JSON.parse(filesystem.readFileSync(`./cards/cards-${locales[index].symbol}.json`)));
var recentState = hash(JSON.parse(body));
/If the local card base is not up to date, add locale to array
if(localState !== recentState){
outdatedLanguages.push(locales[index].symbol);
}
);
}
//Return outdatedLanguages array
return outdatedLanguages;
}
To get the correct data, you need to use promises. Instead of request callback, use promise.
Because checkForDiff() is an async function, you should return a promise from the function instead of trying to return the outdatedLanguages. For your case, you need to use Promise.all() function because you have multiple async functions. In a sense, Promise.all() waits for all tasks to accomplish. In the other part of the code where you use that function, you should be aware that the function is a promise so you should use it accordingly. Basically, you can do something like this.
function checkForDiff() {
let outdatedLanguages = [];
let promises = [];
var options = {
url: 'https://xxxxxxxxxxxxxxxxxxxxxxxxx',
headers: { 'Key': 'xxxxxxxxxxxxxxxxxxxxxx' }
};
for (let index = 0; index < locales.length; index++) {
//Change url for new https request
options.url = `https://xxxxxxx?locale=${locales[index].symbol}`
promises.push(/* request as promise */);
}
return Promise.all(promises).then(() => outdatedLanguages);
}
You call the function like this.
checkForDiff().then((outdatedLanguages) => {
// outdatedLanguages is the array you want
})
For request promise you can use request-promise package. Use the command npm install --save request-promise. Then include the package var rp = require('request-promise');. An example request is as following:
var options = {
uri: 'https://api.github.com/user/repos',
qs: {
access_token: 'xxxxx xxxxx' // -> uri + '?access_token=xxxxx%20xxxxx'
},
headers: {
'User-Agent': 'Request-Promise'
},
json: true // Automatically parses the JSON string in the response
};
rp(options)
.then(function (repos) {
console.log('User has %d repos', repos.length);
})
.catch(function (err) {
// API call failed...
});

C# 500 Internal Server Error MongoDB

I've been trying to develop some api controller in ASP.NET that comunicates with mongoDB. In same controller I have few post/get methods, and they are working just fine. When I want to update collection in mongoDB, i call post method and when debbuging, all fields in that method are filled, but in return i get 500 error. Any idea where is the problem? The code that I use is:
JavaScript
comment.id += id;
comment.comment += test;
var newCommentUrl = 'api/PostInfo/' + comment;
postDataToDatabase(comment, newCommentUrl);
function postDataToDatabase(data, url) {
$.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
url: url,
type: 'POST',
contentType: 'application/json;',
data: JSON.stringify(data),
success: function (valid) {
if (valid) {
} else {
}
}
});
ASP.NET Controller Method
[HttpPost]
[Route("api/PostInfo/{Comment}")]
public async void Post(Comment comment)
{
BsonObjectId oldId = new BsonObjectId(new ObjectId(comment.id.ToString()));
var mongoDbClient = new MongoClient("mongodb://127.0.0.1:27017");
var mongoDbServer = mongoDbClient.GetDatabase("nmbp");
var collection = mongoDbServer.GetCollection<PostInfo>("post");
var filter = Builders<PostInfo>.Filter.Eq(e => e._id, oldId);
var update = Builders<PostInfo>.Update.Push("post_comments", comment.comment);
await collection.FindOneAndUpdateAsync(filter, update);
}
It looks like method is called, but for some reason it returns 500.
If you are using async await pattern in your code, you must always as a best practice return a Task object when the method returns a void i.e. does not return any object.
In your situation, you need to use the following action method that is returning a Task object rather than the original one in which a void was being returned.
[HttpPost]
[Route("api/PostInfo/{Comment}")]
public async Task Post(Comment comment)
{
BsonObjectId oldId = new BsonObjectId(new ObjectId(comment.id.ToString()));
var mongoDbClient = new MongoClient("mongodb://127.0.0.1:27017");
var mongoDbServer = mongoDbClient.GetDatabase("nmbp");
var collection = mongoDbServer.GetCollection<PostInfo>("post");
var filter = Builders<PostInfo>.Filter.Eq(e => e._id, oldId);
var update = Builders<PostInfo>.Update.Push("post_comments", comment.comment);
await collection.FindOneAndUpdateAsync(filter, update);
}
This is according to Microsoft documentation at this URL: Async Await Best Practice
In the following example, async method Task_MethodAsync doesn't contain a return statement. Therefore, you specify a return type of Task for the method, which enables Task_MethodAsync to be awaited. The definition of the Task type doesn't include a Result property to store a return value.
A code sample from above documentation illustrating this best practice is as given below.
// TASK EXAMPLE
async Task Task_MethodAsync()
{
// The body of an async method is expected to contain an awaited
// asynchronous call.
// Task.Delay is a placeholder for actual work.
await Task.Delay(2000);
// Task.Delay delays the following line by two seconds.
textBox1.Text += String.Format("\r\nSorry for the delay. . . .\r\n");
// This method has no return statement, so its return type is Task.
}

How to return value in Meteor.JS from HTTP.call "GET"

I'm writing a meteor method, which should return a Facebook response for HTTP.call on graph api, but HTTP.call has only a callback function to show error/response, so I can't take this data outside, and Method can not return any value.
Here's my method code:
loadUserFBEvents: function () {
var accessToken = Meteor.user().services.facebook.accessToken;
var query = "me?fields=likes.limit(5){events{picture,cover,place,name,attending_count}}";
console.log(
HTTP.call("GET", "https://graph.facebook.com/" + query + "&access_token=" + accessToken + "", function(error,response){
if(error){
return error;
}
if(response){
return response;
}
})
);
}
Don't pass a callback to get the HTTP to return. You're also able to pass off URL parameters quite easily:
var result = HTTP.call("GET", "https://graph.facebook.com/me", {
params: {
access_token : Meteor.user().services.facebook.accessToken,
fields : "likes.limit(5){events{picture,cover,place,name,attending_count}}"
}
});
console.log(result);
You need to either log or use the response from inside the callback or use Meteor.wrapAsync to make it synchronous so that it returns the way you're expecting it to above.
http://docs.meteor.com/#/full/meteor_wrapasync

How to query the next set of records from an ajax call?

I am querying salesforce database to get some data. The query result will return a max of 2000 records in one response and will also return the "nextRecordsUrl" parameter, using which we can fetch the next set of results. So I am able to achieve this by calling the same method again in the done function of the $.ajax(). I wanted to know if there was any better way to do it?
function stringSearch(queryParam){
var sessionCookie = getCookie('sid');
var currentDomain = window.location.host;
queryParam = queryParam== undefined || queryParam =='' ? "/services/data/v28.0/query/?q=SELECT+Name+from+Account" : queryParam;
$.ajax({
url : "https://"+currentDomain+queryParam,
headers : {"Authorization": "Bearer "+ sessionCookie},
contentType : "application/json"
}).done(function(res){
//do some processing with the result
processingFunction(res.records);
if(res.nextRecordsUrl){
//call the same method with different parameters
stringSearch(res.nextRecordsUrl);
}else{
//Done with all the processing proceed to final actions
}
}).fail(function(err){
alert('Oops!! We were unable to fetch the data you requested!\n'+JSON.stringify(err)+'\n ');
});
}
function processingFunction(){
//use the array and do some processing.
}

Categories