So I created an ajax request which is here
function postForm(url, data) {
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.send(data);
xhr.onreadystatechange = function () {
const DONE = 4; // readyState 4 means the request is done.
const OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
const requestMessage = xhr.responseText;
console.log(requestMessage); // 'This is the returned text.'
const success = requestMessage.search(1);
const error = requestMessage.search(0);
if(success !== -1) {
console.log("success");
removeClass(modal, 'is-active');
closeModal();
window.location.reload();
} else {
console.log("error");
const parent = findAncestor(this, 'folder');
const errorMessage = document.createElement('div');
errorMessage.className = "errorMessage";
errorMessage.innerHTML = requestMessage;
errorMessage.innerHTML = requestMessage.replace('0','');
parent.append(errorMessage);
};
} else if (xhr.status === INT_ERROR) {
console.log(xhr.responseText);
} else {
console.log('Error: ' + xhr.status); // An error occurred during the request.
}
}
};
}
and im having an issue with this part. I want be able to generalize this. when a user presses a button that calls this ajax call, the ajax calls the parent of what they clicked and finds the ancestor and adds errorMessage to the parent of that element. how can i generalize this ajax?
console.log("error");
const parent = findAncestor(this, 'folder');
const errorMessage = document.createElement('div');
errorMessage.className = "errorMessage";
errorMessage.innerHTML = requestMessage;
errorMessage.innerHTML =
requestMessage.replace('0','');
parent.append(errorMessage);
Related
I did a function to show a div when i open my html(its working fine, the div shows at open), but i get this error:
var getJSON = function (url, callback) {
var ajax = new XMLHttpRequest();
ajax.open('GET', url, true);
ajax.responseType = 'json';
ajax.onreadystatechange = function () {
var status = ajax.status;
if (status === 200) {
callback(status, ajax.response);
} else {
callback(null, ajax.response);
}
};
ajax.send();
};
getJSON('games.json', function (err, data) {
if (err === null) {
console.log('Error' + err);
} else {
var bets = document.getElementById('bets-container-lotos');
bets.innerHTML = '';
bets.innerHTML +=
'<button id="bets-lotofacil-color" class="bets-lotofacil" onclick=lotofacil()>' +
data.types[0].type +
'</button>';
}
});
I would like to port this open source Python library for Google Reminders to JavaScript:
https://github.com/jonahar/google-reminders-cli
I have ported the authorization with the help of https://developers.google.com/identity/protocols/OAuth2UserAgent
My JavaScript version: https://github.com/Jinjinov/google-reminders-js
Now I need to port the Python's oauth2client POST request:
body = {
'5': 1, # boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, # number number of reminders to retrieve
}
HEADERS = {
'content-type': 'application/json+protobuf',
}
response, content = self.auth_http.request(
uri='https://reminders-pa.clients6.google.com/v1internalOP/reminders/list',
method='POST',
body=json.dumps(body),
headers=HEADERS,
)
My XMLHttpRequest POST request returns:
HTTP 400 - Bad Request - if I use 'application/x-www-form-urlencoded'
HTTP 401 - Unauthorized - if I use 'application/json'
My code (full code with authorization and access token is on GitHub):
function encodeObject(params) {
var query = [];
for (let key in params) {
let val = encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
query.push(val);
}
return query.join('&');
}
function list_reminders(num_reminders, access_token, callback) {
var body = {
'5': 1, // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, // number of reminders to retrieve
};
body['access_token'] = access_token;
//body = JSON.stringify(body);
body = encodeObject(body);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + body);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
//xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list');
//xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
var content_dict = JSON.parse(xhr.response);
if (!('1' in content_dict)) {
console.log('No reminders found');
}
else {
var reminders_dict_list = content_dict['1'];
var reminders = [];
for(var reminder_dict of reminders_dict_list) {
reminders.push(build_reminder(reminder_dict));
}
callback(reminders);
}
}
else if (xhr.readyState === 4 && xhr.status === 401) {
callback(null);
}
}
//xhr.send(body);
xhr.send(null);
}
I was trying to send both, the body and the access token in the same way.
The solution is to send the access token as url encoded and the body as json:
function list_reminders(num_reminders, access_token, callback) {
/*
returns a list of the last num_reminders created reminders, or
None if an error occurred
*/
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + 'access_token=' + access_token);
xhr.setRequestHeader('Content-type', 'application/json+protobuf');
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
var content_dict = JSON.parse(xhr.response);
if (!('1' in content_dict)) {
console.log('No reminders found');
}
else {
var reminders_dict_list = content_dict['1'];
var reminders = [];
for(var reminder_dict of reminders_dict_list) {
reminders.push(build_reminder(reminder_dict));
}
callback(reminders);
}
}
else if (xhr.readyState === 4 && xhr.status === 401) {
callback(null);
}
}
var body = {
'5': 1, // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
'6': num_reminders, // number of reminders to retrieve
};
xhr.send(JSON.stringify(body));
}
The app that I'm working on does not respond with the API address. I only get the ajax responding, but not the weather api that I'm trying to call.
I've tried everything that I could think of with my current knowledge.
let search = document.getElementById("search-bar");
let temp = document.getElementById("temperature");
let input = document.getElementById("input");
let city = document.getElementById("city");
const key = "";
input.addEventListener("keyup", enter);
function enter(event) {
if (event.key==="Enter") {
details();
}
}
function details() {
if (searchInput.value === ""){
} else {
let searchLink = "https://api.openweathermap.org/data/2.5/weather?q={}" + searchInput.value + "&appid=" + key;
httpRequestAsync(searchLink, talk)
}
}
function talk(talking){
let jsonObject = JSON.parse(talking);
city.innerHTML = jsonOject.name;
temp.innerHTML = parseInt(parseInt(jsonObject.main.temp - 273) + "°");
}
function httpRequestAsync(url,callback){
var httpRequest=new XMLHttpRequest();
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState == 4 && httpRequest.status == 200)
callback(httpRequest.responseText);
}
request.open("GET", url, true); // true for asynchronous
request.send();
}
The expected outcome should be the weather api being called and displayed information in the console.
Try replacing last function with this:
function httpRequestAsync(url,callback){
var httpRequest=new XMLHttpRequest();
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState == 4 && httpRequest.status == 200)
callback(httpRequest.responseText);
}
httpRequest.open("GET", url, true); // true for asynchronous
httpRequest.send();
}
I just corrected variable naming
My function has to call two endpoints and concat them in one string at the same time. My code is simply a function that is getting two endpoints at the same time and print it in console.
But the same function has to concat them to one string.
I tried to create separated variables contains each call and then simply concat them, but the result hadn't been any different.
I read about it for couple of hours, and I see no, even the smallest tip anywhere.
EDIT: Please mind that each endpoint is an actual array.
function endpointsToOneString() {
const Http = new XMLHttpRequest();
const url = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log(Http.responseText)
}
}
const HttpTwo = new XMLHttpRequest();
const urlTwo = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
HttpTwo.open("GET", urlTwo);
HttpTwo.send();
HttpTwo.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
console.log(Http.responseText)
}
}
}
endpointsToOneString();
In this case you should use Promise feature of javascript.
Here you can learn how to promisify your native XHR. Morever, Here you can find about promise chaining.
I have just added Promise in your code but it needs to be refactored.
Update: From comment, you want your response texts as a plain string. But we are actually getting a JSON array as response. So, we need to parse it using JSON.parse() function to make it an array object. Then we need to use .join() method to join all element of the array into a string. See the code below:
function endpointsToOneString() {
var requestOne = new Promise(function(resolve, reject){
const Http = new XMLHttpRequest();
const url = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
Http.open("GET", url);
Http.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(Http.response);
} else {
reject({
status: this.status,
statusText: Http.statusText
});
}
};
Http.onerror = function () {
reject({
status: this.status,
statusText: Http.statusText
});
};
Http.send();
});
var requestTwo = new Promise(function(resolve, reject){
const HttpTwo = new XMLHttpRequest();
const urlTwo = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
HttpTwo.open("GET", urlTwo);
HttpTwo.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(HttpTwo.response);
} else {
reject({
status: this.status,
statusText: HttpTwo.statusText
});
}
};
HttpTwo.onerror = function () {
reject({
status: this.status,
statusText: HttpTwo.statusText
});
};
HttpTwo.send();
});
Promise.all([
requestOne,
requestTwo
]).then(function(result){
var response = JSON.parse(result[0]).join();
response += JSON.parse(result[1]).join();
console.log(response);
});
}
endpointsToOneString();
I understand you want to concat the result of two parallel requests. In that case you can use a library like axios. From their docs
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
// Both requests are now complete
}));
So for your example:
function getEndpoint1() {
return axios.get('https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json');
}
function getEndpoint2() {
return axios.get('https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json');
}
axios.all([getEndpoint1(), getEndpont2()])
.then(axios.spread(function (resp1, resp2) {
// Both requests are now complete
console.log(resp1 + resp2)
}));
try to have a look on the Promise.all method:
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
As in this answer you should wrap your XHR in a Promise and then handle resolving of all function call. In this way you can access endpoint results in order.
Here's a working fiddle:
function makeRequest(method, url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function() {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function() {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
let url1 = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
let url2 = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json'
Promise.all([makeRequest('GET', url1), makeRequest('GET', url2)])
.then(values => {
debugger;
console.log(values);
});
https://jsfiddle.net/lbrutti/octys8k2/6/
Is it obligatory for you to use XMLHttpRequest? If not, u had better use fetch, because it returns Promise and with Promise it would be much simpler.
Rather than immediately printing them, save them to local variables, then print them at the end:
function endpointsToOneString() {
let response; // this line here declares the local variable
results = 0; // counts results, successful or not
const Http = new XMLHttpRequest();
const url = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response = Http.responseText; //save one string
}
if (this.readyState == 4) {
results++;
}
}
const HttpTwo = new XMLHttpRequest();
const urlTwo = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
HttpTwo.open("GET", urlTwo);
HttpTwo.send();
HttpTwo.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response += HttpTwo.responseText // save the other string
}
if (this.readyState == 4) {
results++;
}
}
while(results < 2) {} //loops until both requests finish, successful or not
console.log(response); //print total string
}
endpointsToOneString();
Also, HttpTwo's onreadystatechange function is calling for Http.responseText, rather than HttpTwo.responseText. Fix that as well for best results.
EDIT: Thanks for the tip, Jhon Pedroza!
EDIT: Noah B has pointed out that the above is dirty and inefficient. They are entirely correct. Better version based on their suggestion, credit to them:
function endpointsToOneString() {
let response1 = '', response2 = ''; // this line declares the local variables
const Http = new XMLHttpRequest();
const url = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response1 = Http.responseText; //save one string
checkResults(response1, response2);
}
}
const HttpTwo = new XMLHttpRequest();
const urlTwo = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
HttpTwo.open("GET", urlTwo);
HttpTwo.send();
HttpTwo.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response2 = HttpTwo.responseText; // save the other string
checkResults(response1, response2);
}
}
}
function checkResults(r1, r2) {
if (r1 != '' && r2 != '') {
console.log(r1 + r2);
}
}
endpointsToOneString();
function endpointsToOneString() {
var response;
const Http = new XMLHttpRequest();
const url = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response = this.responseText;
HttpTwo.open("GET", urlTwo);
HttpTwo.send();
}
}
const HttpTwo = new XMLHttpRequest();
const urlTwo = 'https://baconipsum.com/api/?type=all-meat¶s=3&start-with-lorem=1&format=json';
HttpTwo.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
response += this.responseText;
console.log(response);
}
}
}
endpointsToOneString();
check this out. there's just minimal editing to your code.
I have two ajax calls , the second one should be triggered only after the first ajax is success. Every time the first ajax returning sucess , but I always get error for the second one.
function proceedWithUnlock(target, address, PARAMS) {
target.style.backgroundColor = 'yellow';
target.nextElementSibling.innerHTML = 'processing....';
target.nextElementSibling.style.backgroundColor = 'yellow';
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseText.match('Success')) {
target.nextElementSibling.innerHTML = 'Success!!!';
target.nextElementSibling.style.backgroundColor = 'lightgreen';
lockTheNumber(target, address1, PARAMS1);
} else {
target.nextElementSibling.innerHTML = 'FAILED';
target.style.backgroundColor = 'red';
target.nextElementSibling.style.backgroundColor = 'red';
}
} else {
target.nextElementSibling.innerHTML = 'FAILED';
target.style.backgroundColor = 'red';
target.nextElementSibling.style.backgroundColor = 'red';
}
}
}
client.open("POST", address);
client.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
client.send(PARAMS);
}
function lockTheNumber(target, address1, PARAMS1) {
target.nextElementSibling.nextElementSibling.innerHTML = 'processing....';
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'yellow';
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if (this.readyState == 4) {
if (this.status == 200) {
if (this.responseText.match('Success')) {
target.nextElementSibling.nextElementSibling.innerHTML = 'Success11111!!!';
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'lightgreen';
target.style.backgroundColor = 'lightgreen';
} else {
target.nextElementSibling.nextElementSibling.innerHTML = 'FAILED 1';
target.style.backgroundColor = 'red';
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'red';
}
} else {
target.nextElementSibling.nextElementSibling.innerHTML = 'UNABLE TO BLOCK 2';
target.style.backgroundColor = 'red';
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'red';
}
}
}
client.open("POST", address);
client.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
client.send(PARAMS);
}
Error Message: "Error in completing operation "
Create a new XMLHttpRequest object instead of reusing the old one. It is out of scope.
...
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'yellow';
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
...
Your other XMLHttpRequest object is out of scope. You need to create a new object in your second function:
function lockTheNumber(target, address1, PARAMS1){
target.nextElementSibling.nextElementSibling.innerHTML = 'processing....';
target.nextElementSibling.nextElementSibling.style.backgroundColor = 'yellow';
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
You have added the jquery tag so I assume you also can take advantage of the library. JQuery supports promises or in JQuery syntax it's called deferred.
This helps to structure ajax calls with the then operator
More information in the docs: https://api.jquery.com/deferred.then/
JQuery also comes with a god wrapper for ajax calls.