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))
Related
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.
I am new to javascript and trying to write a script that will send multiple HTTP requests to a web server using Axios. The server is designed in such a way that it will send response randomly to a request. Now, I want the script to stop sending the requests once it receives one response. The basic code which I could write yet is:
while (1) {
axios.get('http://localhost:8080/ubuntu_default.html', { withCredentials: true }).then(function (response) {
document.body.innerHTML = generateSuccessHTMLOutput(response);
break;
});
function generateSuccessHTMLOutput(response) {
return response.data;
}
}
Assume this .js file will be present in the client's browser.
Edit: based on this comment op just wants to poll an endpoint and stop once he gets a response.
Example code:
(async() {
let r = await poll('http://localhost:8080/ubuntu_default.html');
console.log(r);
})();
async function poll(endpoint) {
let countOfError = 0;
const maxErrors = 10;
let resp = null;
while (true) {
try {
resp = await axios.get(endpoint, { withCredentials: true }));
//check if resp is "success" then break;
//What does a successful response look like?
if (resp.data.success) break;
} catch (e) {
//console.error(e); optional
countOfErrors += 1;
if (countOfErrors > maxErrors) break;
}
}
return resp;
}
old answer
You could use something like Promise.race
let promises = [];
for (let i = 0; i<10; i++)
promises.push(
axios.get('http://localhost:8080/ubuntu_default.html',
{ withCredentials: true }));
Promise.race(promises).then( generateSuccessHTMLOutput );
//Called with whichever promise fulfills first
i would like to get help with a problem im trying to solve, so the problem is that i have to call two APIs url. the second depend on the first (in the first fetch im getting some basic info , including ids, in the second fetch i want to fetch data based on the ids from the first fetching).
i always getting this error:
Uncaught TypeError: Cannot read property 'length' of undefined
probably my approach is not correct. i tried few things like putting the second function inside the first function, i tried to do it without async, its only working when i have two different buttons.
i guess the async is causing this problem.(its trying to get the length before the respond)
please help me with this one. i would love to get some insight about approach or any way to solve it.
thanks in advance.
this is the problematic code
//recipies by ingredients array
var displayData = [];
//full recipies array
var displayRecipes = [];
document.getElementById("search").addEventListener("click", function () {
var l = document.getElementsByClassName("ingInput").length
var ing = document.getElementById('id').value
var ing1 = ''
//getting all the values from the inputs so i can search it in the api url
for(var i = 1; i<l ;i++){
ing1 += ',' + document.getElementsByClassName("ingInput")[i].value
}
//async get request for the api url
async function postData(url = '') {
const response = await fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
});
return response.json(); // parses JSON response into native JavaScript objects
}
//the api url with the inputs values for searching by ingredeints
postData('https://api.spoonacular.com/recipes/findByIngredients?ingredients='+ ing + ing1 + '&number=10&apiKey=API_KEY')
.then((data) => {
displayData.push(data); // JSON data parsed by `response.json()` call
console.log('done')
});
})
//second func
document.getElementById("search").addEventListener("click", function () {
//trying to get data from this array, here i have error.
var l = displayData[0].length
var ids = []
for(var i = 0; i<l ;i++){
ids.push(displayData[0][i].id)
}
async function postData(url = '') {
// Default options are marked with *
const response = await fetch(url, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
});
return await response.json(); // parses JSON response into native JavaScript objects
}
postData('https://api.spoonacular.com/recipes/informationBulk?ids='+ids.toString()+'&apiKey=API_KEY')
.then((data) => {
displayRecipes.push(data); // JSON data parsed by `response.json()` call
console.log(displayRecipes)
});
})```
How about you make the second fetch only if you have data from the first? This way, when no data exists, the button fetches initial data. If data already exists, it fetches the additional info. So you have a single listener:
document.getElementById( "search" ).addEventListener( "click", function () {
if ( displayData.length === 0 ) {
// Call first function
} else {
// Call second function
}
})
i found a solution to my problem, im not sure if its the best way to do it, but its working fine for me.
so the dom looks like this:
(i added onclick to the search button)
<div id="container">
<!-- first input for the first ingrediant you can search -->
<input type="text" class="ingInput" id="id" placeholder="ingrediant" onfocus="auto(this)">
</div>
<!-- search button, first bring the recipies based on ingredient, then the full recipies based on ids from the first fetch data -->
<button id="search" onclick="asyncCall()">Search</button>
<!-- add new input for more ingrediant -->
<button id="add" onclick="add()">Add</button>
<!-- display the element i have created from the data i have -->
<div id="display">
</div>
<!-- for jquery pagination -->
<button id="btn_prev">Prev</button>
<button id="btn_next">Next</button>
page: <span id="page"></span>
and the javascript for getting the data (first from the first api link then from the second api link):
//recipies by ingredients array
var displayData = [];
//full recipies array
var displayRecipes = [];
async function search(){
var l = document.getElementsByClassName("ingInput").length
var ing = document.getElementById('id').value
var ing1 = ''
//getting all the values from the inputs so i can search it in the api url
for(var i = 1; i<l ;i++){
ing1 += ',' + document.getElementsByClassName("ingInput")[i].value
}
//the api url with the inputs values for searching by ingredeints
await fetch('https://api.spoonacular.com/recipes/findByIngredients?ingredients='+ ing + ing1 + '&number=10&apiKey=API_KEY', {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
}
}).then(res => res.json())
.then((data) => {
displayData.push(data); // JSON data parsed by `response.json()` call
console.log('done')
});
}
async function getRecipes(){
var l = displayData[0].length
var ids = []
for(var i = 0; i<l ;i++){
ids.push(displayData[0][i].id)
}
await fetch('https://api.spoonacular.com/recipes/informationBulk?ids='+ids.toString()+'&apiKey=API_KEY',{
method: 'GET', // *GET, POST, PUT, DELETE, etc.
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
}
})
.then(res => res.json())
.then((data) => {
displayRecipes.push(data); // JSON data parsed by `response.json()` call
console.log(displayRecipes)
});
}
async function asyncCall() {
console.log('calling');
const resultSearch = await search();
console.log('done await search');
console.log('calling2');
const resultRecipies = await getRecipes();
console.log('done await recipes');
}```
I'm adding a contact me section to a website. I want to be able to send the data from the forms with JS, and then receive and do something with the data with Node. I understand that there are frameworks and libraries that can handle this stuff, but I would like to build it from scratch so that I have a better understanding of what is happening.
I currently have a section of JS (see below) that is taking the form data, and sending it as a POST request to the node script, but I can't seem to wrap my head around what is happening with node, or how to receive the data with the node script. Any help in pointing me in the right direction is greatly appreciated.
const name = $(".name");
const email = $(".email");
const message = $(".message");
const submitButton = $(".submitButton");
const nameRegex = /([a-zA-Z\s-])/g;
const emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/g;
const messageRegex = /([a-zA-Z\s.,?!$%&])/gm;
const url = "../node/contactMeSubmissionHandler.js"
submitButton.click(function(){
let nameContents = name.val().match(nameRegex).join("");
let emailContents = email.val().match(emailRegex).join("");
let messageContents = message.val().match(messageRegex).join("");
// if (emailRegex.test(emailContents) == true) {
// let emailValid = emailContents;
// } else {
// console.log("Email is invalid");
// };
const data = {
email: emailContents,
name: nameContents,
message: messageContents
}
$.post(url, data, function(data, status){
console.log(`${data} and status is ${status}`);
})
})
I like to write from scratch too. Here is working code which is called from a command line to get a token.
// clientEx.js
var http = require('http');
var fs = require('fs');
const _SERVER = "dcsmail.net"; /* dcsmail.net */
// Callback function is used to deal with response
//
var callback = function (response)
{
// update stream with data
var body = '';
response.on('data', function(data) {
body += data;
});
response.on ('end', function()
{
// Data received completely.
fs.writeFileSync ("temp.lst", body, 'utf8');
// console.log ("clientEx.js received: " + body);
});
}
if ((process.argv[2] == null) || (process.argv[3] == null) || (process.argv[4] == null) || (process.argv[5] == null))
{
console.log ("clientEx.js usage:<user email> <user password> <destination> <GUID>");
}
else
{
var Ef_email = encodeURI (process.argv[2]);
var Ef_pass = encodeURI (process.argv[3]);
var Ef_dest = encodeURI (process.argv[4]);
var Ef_guid = encodeURI (process.argv[5]);
var post_data = ("f_email=" + Ef_email +
"\&" + "f_pass=" + Ef_pass +
"\&" + "f_dest=" + Ef_dest +
"\&" + "f_guid=" + Ef_guid);
// Options to be used by request
var options = {
host: _SERVER,
port: '80',
path: '/DCSM/tokenP10.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength (post_data)
}
};
// console.log ("clientEx.js using " + _SERVER + ":" + options.port + options.path);
// request the token from the host
try
{
var req = http.request (options, callback);
req.write (post_data);
req.end();
}
catch (error)
{
fs.writeFileSync ("temp.lst", "Host access failed\n", 'utf8');
}
}
You should be able to adapt that to your needs.
Use this code to create a server and check the log in console for different request attributes.
const http = require('http');
http
.createServer((request, response) => {
console.log(request);
response.end();
})
.listen(3000);
Make GET and POST request to http://localhost:3000/ and look for method, headers etc.
See more here and here.
I've been tinkering with codeceptjs and I wanna know if there is a way to do a sendPostRequest without a payload.
Here's my sample:
Scenario('Sample', async (I) => {
var resp,
args = {
"TABLE_ID": 748,
"STATUS" : 5
};
var reqHead = {
'Accept' : 'application/json',
'User-Agent': 'Unirest Node.js'
};
var urlSamp = 'table/sample?TABLE_ID=' + args.TABLE_ID + '&STATUS=' + args.STATUS, args;
I.haveRequestHeaders(reqHead);
resp = await I.sendPostRequest(urlSamp);
resp = resp.body;
resp = JSON.stringify(resp);
I.say(resp ? resp : "Err: " + resp + " -- Msg: System may not be currently running.");
});
So, is this line correct?
resp = await I.sendPostRequest(urlSamp);
Actually, I've already done the line of code above, however it resulted into an error.
I've also tried the following below:
resp = await I.sendPostRequest(urlSamp, '');
Or...
resp = await I.sendPostRequest(urlSamp, null);
And...
resp = await I.sendPostRequest(urlSamp, {});
However, none of the above worked.
Please advise. Thanks in advance.
I got it.
resp = await I.sendPostRequest(urlSamp);
Above line alone is enough and actually works without the payload.
My main issue was not the codeceptjs, nor the payload, but rather my system itself.