Console.log() does not await in async function [duplicate] - javascript

This question already has answers here:
In JavaScript how do I/should I use async/await with XMLHttpRequest?
(5 answers)
How do I convert an existing callback API to promises?
(24 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I'm trying to get the exchange rates to calculate approximate prices in dollars.
I want to get result in console.log(currency), but I just got undefined over an over
Pls help)
(async function() {
let date = new Date();
let currency = await searchCurrency();
await console.log(currency) // result expected
})();
function searchCurrency(){
if(!localStorage.currency||!JSON.parse(localStorage.currency).date==date.getDate()+'.'+date.getMonth())
{
return getCurrency(date);
} else {
console.log('LS the same!')
return JSON.parse(localStorage.currency).val;
}
}
function getCurrency(date){
var answer;
var xhr = new XMLHttpRequest();
var apiKey = "my_key";
var query = 'RUB' + "_" + 'USD';
var url =
"https://free.currconv.com/api/v7/convert?q=" +
query +
"&compact=ultra&apiKey=" +
apiKey;
xhr.open("GET", url);
xhr.onload = function () {
if (xhr.status != 200) {
console.log(`Error ${xhr.status}: ${xhr.statusText}`);
answer = 80;
} else {
console.log(`${xhr.response}`);
localStorage.setItem('currency', JSON.stringify({val: JSON.parse(xhr.response)[query], date: date.getDate()+'.'+date.getMonth()}));
answer = JSON.parse(xhr.response)[query];
}
};
xhr.send();
return answer;
}
UPD: Thanks for comments and similar questions. I wrapped my request function in a promise like below and it's working now :) Posting that here if it'll be useful for someone in future.
(async function() {
let date = new Date();
let currency;
if (localStorage.currency&&JSON.parse(localStorage.currency).date==date.getDate()+'.'+date.getMonth()){
currency = JSON.parse(localStorage.getItem('currency')).val;
} else {
currency = await makeRequest(date);
localStorage.setItem('currency', JSON.stringify({val: currency, date: date.getDate()+'.'+date.getMonth()}))
}
await console.log(currency);
})();
function makeRequest(date) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://free.currconv.com/api/v7/convert?q=RUB_USD&compact=ultra&apiKey='secret_api_key');
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response).RUB_USD);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}

Related

Unable to pass return value of a XMLHttpRequest to a variable [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I am unable to assign the return value of a XMLHttpRequest (which searches for a string in a tiny csv file and returns its value in the desired language) to a variable. It always says that the string is undefined.
I have even added a delay to give time to the XMLHttpRequest to read the csv file (which is just a few lines btw) but to no avail.
Any suggestions please! I'm stuck!
function DisplayItemInCorrectLanguage()
{
var str = GetLocalizedTerm ("CBRAND", Language);
console.log('str: ', str); //Does not work. Error: 'str: undefined'
}
function GetLocalizedTerm (itemname, language)
{
var itn = itemname;
var lng = language;
var oReq = new XMLHttpRequest();
oReq.onload = function()
{
//console.log("String is: ", this.responseText); //log is correct: 'String is: CAR BRAND'
//return this.responseText; //Does not return any value to DisplayItemInCorrectLanguage()
};
oReq.open("get", "GetLocalizedTermFromDictionary.php?itemname=" + itn + "&LANG=" + lng, true);
oReq.send();
}
This should work.
function GetLocalizedTerm (itemName, language){
return new Promise((resolve, reject) => {
var oReq = new XMLHttpRequest();
oReq.open("get", "GetLocalizedTermFromDictionary.php?itemname=" + itemName + "&LANG=" + language, true);
oReq.onload = () => {
if (oReq.status >= 200 && oReq.status < 300) {
resolve(oReq.response);
} else {
reject(oReq.statusText);
}
};
oReq.onerror = () => reject(oReq.statusText);
oReq.send();
});
}
async function DisplayItemInCorrectLanguage()
{
const language='en'
var str = await GetLocalizedTerm ("CBRAND", language);
console.log('str: ', str);
}

How to concat two called endpoints to one string and print it in console

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&paras=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&paras=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&paras=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&paras=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&paras=3&start-with-lorem=1&format=json');
}
function getEndpoint2() {
return axios.get('https://baconipsum.com/api/?type=all-meat&paras=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&paras=3&start-with-lorem=1&format=json';
let url2 = 'https://baconipsum.com/api/?type=all-meat&paras=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&paras=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&paras=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&paras=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&paras=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&paras=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&paras=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.

js xml response return undifined

Please I need help !
To begin I don't speaking very well english sorry for the mistakes
So I'm tryng to receive a JSON Object with this code :
function uhttp(url){
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
console.log(xhr.response)
return xhr.response;
}
};
xhr.send();
console.log('exit')
};
but when I use the function https like this :
`
( ()=>{
var perso =uhttp('bd.php?table=charac')
for (var i = 0; i < perso.lenght; i++) {
document.getElementbyID('container').append('<ul>'+perso[i].nom+'</ul>')
}
})()
`
perso he's undifined...
here the console of index.html
I've the impression that we'are exit the function before that whe receive the resonse and that is why the function return a null
Of course before to ask my question I'have make some research but no one working in my case....
Thank you for yours anwsers
It happens because you aren't returning value from uhttp() function but from anonymous function (xhr.onload).
In order to access this value after the AJAX call is over use promises:
function uhttp(url){
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
resolve(xhr.response);
return;
}
reject();
};
xhr.onerror = function() {
reject()
};
xhr.send();
})
}
And use it like so:
uhttp('bd.php?table=charac').then(function(result) {
var person = result;
for (var i = 0; i < perso.lenght; i++) {
document.getElementbyID('container').append('<ul>'+perso[i].nom+'</ul>');
}
}).catch(function() {
// Logic on error
});

xhr promise returns error

I want to show answer from XMLhttpRequest in other function (not in onreadystatechangefunction).
I have code
setInterval(function() {
let requestPromise = new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('POST', "location?act=update&id=<?php echo $id; ?>", true);
xhr.send();
xhr.onreadystatechange = function(){
if(this.readyState==4){
if(this.status == 200){
if(this.responseText){
try{
var data = JSON.parse(this.responseText);
if(data.command=="list"){
var answerLat = parseFloat(data.lat);
var answerLng = parseFloat(data.lng);
var answerAccuracy = String(data.accuracy);
var answerTime = String(data.time);
resolve(answerLat); // Pump answerLat
resolve(answerLng);
resolve(answerAccuracy);
resolve(answerTime);
}
}catch(e){
}
}
}
}
}
});
requestPromise.then(googleMapsFunction); // googleMapsFunction will be called once the request is completed and will get answerLat as the argument
}, 20000);
For example: I have google map in other function. How I can load data (answerLat, answerLng, answerAccuracy and answerTime) from xmlhttpreqest to other function with map (function - googleMapsFunction)?
but when I use it I see error:
Uncaught (in promise) ReferenceError: answerLat is not defined
How I can accept it as a parameter?
I guess the problem is on promise resolving. Try to combine received data into single object and pass it to resolve()
setInterval(function() {
let requestPromise = new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('POST', "location?act=update&id=<?php echo $id; ?>", true);
xhr.send();
xhr.onreadystatechange = function(){
if(this.readyState==4 && this.status == 200 && this.responseText){
try{
var data = JSON.parse(this.responseText);
if(data.command=="list"){
resolve({
answerLat: parseFloat(data.lat),
answerLng: parseFloat(data.lng),
answerAccuracy: data.accuracy,
answerTime: data.time
});
}
}catch(e){
reject(e)
}
}
}
});
requestPromise.then(googleMapsFunction); // googleMapsFunction will be called once the request is completed and will get answerLat as the argument
}, 20000);
const googleMapsFunction = (params) => {
const {answerLat, answerLng, answerAccuracy, answerTime} = params
// ... answerLat, answerLng, answerAccuracy, answerTime
}

Js code does not run sequentially due to asynchronous [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
EDIT: My js code involve asynchronous, so that it actually finishes the second alert() in the ready method before the init() finish executing. Any idea on how to make sure that my second alert() executes after the init()? Thank you in advance.
var notes = [];
$(document).ready(function() {
//var notes = [];
alert("before " + notes.length);
init();
alert("after " + notes.length)
//execute(notes, 0);
});
function init() {
loadJSON(function(response) {
// Parse JSON string into object
var actual_JSON = JSON.parse(response);
var len = actual_JSON.notes.length;
//alert("length is " + len);
for(var i = 0; i < 6; i++) {
notes.push(actual_JSON.notes[i]);
}
//alert("after for loop " + notes.length);
});
}
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'test.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
};
xobj.send(null);
}
Use promise
var notes = [];
$(document).ready(function() {
alert("before " + notes.length);
init()
.then(function(){
alert("after " + notes.length)
})
.catch(function(err){
console.log('error in init()', err)
});
});
function init() {
return new Promise(function(resolve, reject) {
loadJSON(function(response) {
var actual_JSON = JSON.parse(response);
var len = actual_JSON.notes.length;
for(var i = 0; i < 6; i++) {
notes.push(actual_JSON.notes[i]);
}
resolve()
});
});
}
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'test.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
callback(xobj.responseText);
}
};
xobj.send(null);

Categories

Resources