I am having issues correctly setting up my XMLHttpRequest object to POST data to a server. The data (from an HTML form) never seems to get posted, or at least readyState == 4 && status are never reached.
function PostToAPI() {
var payersName = document.forms["myForm"]["payersName"].value;
var recipientPhoneNumber = document.forms["myForm"]["recipientPhoneNumber"].value;
var apiKey = document.forms["myForm"]["apiKey"].value;
var params = "payersName="+payersName+
"&recipientPhoneNumber="+recipientPhoneNumber+
"&apiKey="+apiKey;
alert(params); // Note#1
var Url = "https://api.blackShawls.af/c2b"; // Note#2
var xhr = new XMLHttpRequest();
xhr.open('POST', Url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = processRequest;
function processRequest(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText.headers.Host); // Note#3
}
}
xhr.send(params);
}
Notes
(Note#1) This alert yields the following result:
This suggests that the various fields from the HTML form have been successfully read in, and that everything is working just fine to this point.
(Note#2) The Url value here is fictitious, in contrast to one in my code.
(Note#3) The alert(xhr.responseText.headers.Host); never seems to fire-up, suggesting that the readyState and the status conditions are never met.
Or could it be that the xhr.send(params) is never sent?
Can someone kindly point out where I am going wrong in my code?
Looking forward to your help.
Related
I have a JavaScript function called getAandB which takes a callback. getAandB firstly gets value 'a' using ajax. It then invokes the callback with value 'a' as an argument. The callback gets value 'b' and console.logs both 'a' and 'b' to the console. so I get {"key":"a"} {"key":"b"} in the console.
I thought that the two ajax calls would happen simultaneously / asynchronously. However, they seem to run one after the other ie. synchronously.
The JavaScript code and the PHP code for the ajax requests is shown below:
index.html:
<script>
function getAandB(callback){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-a.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
callback(xhr.responseText)
}
}
xhr.send();
}
function callback(resultA){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-b.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
const resultB = xhr.responseText;
console.log(resultA, resultB);
}
}
xhr.send();
}
getAandB(callback);
</script>
ajax-a.php:
<?php
sleep(5);
$response = [
"key" => "a",
];
echo json_encode($response);
The code for ajax-b.php is the same as for ajax-a.php except the value of $response.key is b not a.
I thought that the above code would result in ajax calls being made simultaneously to get 'a' and 'b'. However if the PHP code sleeps for 5 seconds for both ajax-a.php and ajax-b.php, then it takes 10 seconds for the console.log to appear. If only one of the ajax-?.php scripts sleeps for 5 seconds then it takes 5 seconds for the console.log to appear.
How can I use callbacks to allow me to combine the results of ajax calls, as I have done here, but to make the individual calls happen simultaneously / asynchronously? Alternatively, is not possible to implement this with callbacks?
If you want the request to ajax-b to me made at approximately the same time as the request for ajax-a then you need to make the respective calls to xhr.send() at approximately the same time.
At the moment, the call to ajax-b's send() takes place as part of callback() which you only call after you have received the response to the request for ajax-a.
You then need to add additional logic to determine when you have received both responses so you log both bits of data at the same time (assuming you still want to do that).
A rough and ready way to do that, keeping to your current approach, would look something like this:
function getA(callback){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-a.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
callback(xhr.responseText)
}
}
xhr.send();
}
function getB(callback){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-b.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
const resultB = xhr.responseText;
callback(xhr.responseText)
}
}
xhr.send();
}
function getAandB() {
const data = [];
function callback(responseData) {
data.push(responseData);
if (data.length === 2) {
console.log(...data);
}
}
getA(callback);
getB(callback);
}
getAandB();
We have better tools for that these days though, thanks to promises and modern APIs (like fetch) which support them natively.
async function getAandB() {
const dataPromises = [
fetch("./ajax-a.php").then(r => r.text()),
fetch("./ajax-b.php").then(r => r.text())
];
const data = await Promise.all(dataPromises);
console.log(...data);
}
getAandB();
I tried to edit my question but 'the edit queue was full'.
It took me a while to understand #Quentin's answer but I finally realized it relies on the fact that both instantiations of the callback function are altering the same variable (I think that is called by reference and is the default situation with arrays). Given this, although the instantiations know nothing about each other, it is possible to know when both ajax calls have completed by checking to see if the data array has been updated twice. If it has then both must have completed and data can be consoled out.
There is no need for the getAandB function. This much simpler and less confusing code works exactly the same as Quentin's answer:
<script>
const data = [];
function getA(){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-a.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
data.push(xhr.responseText);
if (data.length === 2){
console.log(...data);
}
}
}
xhr.send();
}
function getB(){
const xhr = new XMLHttpRequest();
xhr.open('GET', './ajax-b.php', true);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
data.push(xhr.responseText);
if (data.length === 2){
console.log(...data);
}
}
}
xhr.send();
}
getA();
getB();
</script>
I followed some guides on how to send json objects to the server(written using node.js) and it doesn't work, I have no idea what is wrong. I know that my server works fine since I tested it on postman so it's my js code that's the problem, all the tutorials I see follow a similar XMLHttpRequest format.
this is my code
var ing = new Ingredient(name, date, qty, rp);
var url = "http://localhost:8081/addIngredient";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
//Send the proper header information along with the request
// application/json is sending json format data
xhr.setRequestHeader("Content-type", "application/json");
// Create a state change callback
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Print received data from server
result.innerHTML = this.responseText;
}
};
// Converting JSON data to string
var data = JSON.stringify(ing);
document.write(data);
// Sending data with the request
xhr.send(data);
I used document.write to check where the code stops working but everything passes (since the document.write prints something), I suspect that there is something wrong/missing from xhr.send(data) but I can't tell what. Finally, nothing gets printed from the callback.
It's better to use onload instead of onreadystatechange
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Response length = ${xhr.response.length}`);
// store xhr.response here somewhere
}
};
I have an xmlhttprequest code that is executed on a button, it runs and access the advReqPage.aspx on the first run but when I press the button again, it doesn't access the advReqPage.aspx any more. What is the problem here?
function SaveAdvPayment() {
var xhr = new XMLHttpRequest();
var ornumber = document.getElementById("ORNumber").value;
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// OK
alert('response:' + xhr.responseText);
// here you can use the result (cli.responseText)
} else {
// not OK
alert('failure!');
}
}
}
xhr.open("GET", "Server_Requests/advReqPage.aspx?poo=" + ornumber + "&sess=INSERT", false);
xhr.send();
alert('Saved');
$('#myModal').modal('hide');
}
Probably the first response is getting cached and when you make the second request your browser is not making this new request. This behavior is due to browser locking the cache and waiting to see the result of one request before requesting the same resource again. You can overcome this by making your requests unique like adding random query string.
I am unable to send JSON object to XMLHttpRequest(). However, if I send string data through send(), it works. For example, the following code works:
var xhr = new XMLHttpRequest();
var url = 'https://xyz.info/api/contacts';
xhr.open("POST", url,true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
// Request finished. Do processing here.
}
}
xhr.send("apikey=ee694eabf9e3&firstname=Raja1&lastname=Kumars&phone=123456");
However, if I try to send data using JSON, it posts nothing to the url. The following code does not work.
var xhr = new XMLHttpRequest();
var url = 'https://xyz.info/api/contacts';
xhr.open("POST", url,true);
//xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
// Request finished. Do processing here.
}
}
xhr.send(JSON.stringify({
'apikey' :'ee6915d4ee4b4df66bba82277e3',
'firstname' : 'Kumar',
'lastname' : 'Sunder',
'phone':'5557773334'
}));
You're sending very different information in your two calls. Some sample code:
var _stringify = JSON.stringify({
'apikey' :'ee6915d4ee4b4df66bba82277e3',
'firstname' : 'Kumar',
'lastname' : 'Sunder',
'phone':'5557773334'
});
console.log(_stringify);
var _orig = "apikey=ee694eabf9e3&firstname=Raja1&lastname=Kumars&phone=123456"
var _encoded = encodeURI(_stringify);
console.log(_orig);
console.log(_encoded);
when your original string is printed to the console log, it looks as you would expect:
apikey=ee694eabf9e3&firstname=Raja1&lastname=Kumars&phone=123456
when the result of JSON.stringify is printed to the console, it returns:
{"apikey":"ee6915d4ee4b4df66bba82277e3","firstname":"Kumar","lastname":"Sunder","phone":"5557773334"}
That is, it comes complete with lots of extra double quote marks and left and right brackets. If you want to send all of that as a string (as in your initial example), you would need to URI encode the result of the JSON.stringify call. This is what happens with the "_encoded" variable, which contains:
%7B%22apikey%22:%22ee6915d4ee4b4df66bba82277e3%22,%22firstname%22:%22Kumar%22,%22lastname%22:%22Sunder%22,%22phone%22:%225557773334%22%7D
You are sending via a POST action, but then sending the data via a url string. If you want to send it that way you need to set it to GET.
I can make GET calls fine, but I don't know how to make PUT requests. The error I'm getting is "Failed to load resource: too many HTTP redirects"
Code:
var url = "https://{{shop.domain}}/cart.js";
var xhrPut = new XMLHttpRequest();
xhrPut.open("PUT", url, true);
xhrPut.setRequestHeader("Content-Type", "application/json");
xhrPut.send("{\"total_price\":50}");
The JSON that I'm trying to change is this:
{"token":"a97c89f7e2c7c22becab8cfef40fa272","note":null,"attributes":{},"original_total_price":100,"total_price":100,"total_discount":0,"total_weight":0,"item_count":1,"items":[{"id":19673785606,"properties":null,"quantity":1,"variant_id":19673785606,"key":"19673785606:59d774c1f413525441dcb716e0c982e2","title":"Short Sleeve Shirt","price":100,"line_price":100,"original_line_price":100,"total_discount":0,"discounts":[],"sku":"","grams":0,"vendor":"Dev Store","product_id":6213990086,"gift_card":false,"url":"\/products\/short-sleeve-shirt?variant=19673785606","image":"https:\/\/cdn.shopify.com\/s\/files\/1\/1278\/7069\/products\/happyman.jpg?v=1462811058","handle":"short-sleeve-shirt","requires_shipping":true,"product_type":"","product_title":"Short Sleeve Shirt","product_description":"description","variant_title":null,"variant_options":["Default Title"]}],"requires_shipping":true}
The total_price variable is currently 100, I'm trying to set it to 50.
Editing this so I may get answers
I changed the code to the following and then get error 400: bad request
var url = "https://{{shop.domain}}/cart.json";
var xhrPut = new XMLHttpRequest();
xhrPut.open("PUT", url, false);
xhrPut.setRequestHeader("Content-Type", "application/json");
xhrPut.send('{"token":"a97c89f7e2c7c22becab8cfef40fa272","note":null,"attributes":{},"original_total_price":100,"total_price":50,"total_discount":0,"total_weight":0,"item_count":1,"items":[{"id":19673785606,"properties":null,"quantity":1,"variant_id":19673785606,"key":"19673785606:59d774c1f413525441dcb716e0c982e2","title":"Short Sleeve Shirt","price":100,"line_price":100,"original_line_price":100,"total_discount":0,"discounts":[],"sku":"","grams":0,"vendor":"Dev Store","product_id":6213990086,"gift_card":false,"url":"\\/products\\/short-sleeve-shirt?variant=19673785606","image":"https:\\/\\/cdn.shopify.com\\/s\\/files\\/1\\/1278\\/7069\\/products\\/happyman.jpg?v=1462811058","handle":"short-sleeve-shirt","requires_shipping":true,"product_type":"","product_title":"Short Sleeve Shirt","product_description":"description","variant_title":null,"variant_options":["Default Title"]}],"requires_shipping":true}"');
From my knowledge of how the PUT request works, this should overwrite the entire document, but the only changes made were:
The variable total_cost was reduced from 100 to 50
The escape character '\' was used before the characters '\' in the variable 'url' in the array 'item'
Here is a GET request that I am sending before this PUT request, which returns no errors and writes the expected values to console. Note that the errors with the PUT request occur whether this is run or commented out.
var totalCost;
var url = "https://{{shop.domain}}/cart.json";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var resp = xhr.responseText;
console.log(resp);
var json = JSON.parse(resp);
console.log(json);
totalCost = json.total_price;
console.log(totalCost);
}
};
xhr.open("GET", url, false);
xhr.send();
console.log(totalCost);
The only reason this is synchronous is so that I can log the totalCost after the API call.