Reputation: 1803
Here are the functions I have.
async function check_saved_url() {
$.get("https://ipinfo.io/json", function (response) {
current_ip = response.ip;
location_here = response.country;
var ajax_get_url_prefix = base_url + 'getDomain.php?ip=';
var key_ip = current_ip + '@@@' + domain_permanent;
var url = ajax_get_url_prefix + key_ip;
$.get(url, function(data, status) {
console.log("Data: " + data + "\nStatus: " + status);
if (data.includes('0 results')) {
return 'unknown';
} else {
return data;
}
});
}, "jsonp");
}
const func1 = async() => {
return await check_saved_url();
}
const func2 = async() => {
let domain_preference = '';
domain_preference = await func1();
console.log("domain_preference: ",domain_preference);
}
func2();
This method is from this answer.
As you can see, there are two jquery ajax to get data from server.
The problem is, the func1
and func2
never waits until check_saved_url
returns value.
This is what I see in console.
The top red line is the output of func2
, which must wait until check_saved_url
runs, whose result is the following 2 circles.
I am not sure why this persists to happen and hours of copying answers from everywhere didn't help me.
Upvotes: 0
Views: 1786
Reputation: 55739
You probably need to develop your understanding of promises and how async JavaScript works a little.
If you have to use jQuery, you could promisify the jQuery $.ajax
method (which appears to use a very old version of the promise API?), and then use that with modern JS constructs like async
/await
.
const pGet = (url, dataType = 'jsonp') =>
new Promise((success, error) => $.ajax({url, dataType, success, error}))
const IP_URL = 'https://ipinfo.io/json'
const PREFERENCE_URL_PREFIX = 'https://www.example.com/getDomain.php?ip='
const go = async () => {
try {
const { ip } = await pGet(IP_URL)
const preference = await pGet(`${PREFERENCE_URL_PREFIX}${ip}`)
//do something with the preference
} catch(err) {
// handle errors
}
}
go()
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
If you don't have to use jQuery, I'd avoid it and use the fetch API provided by modern host environments.
const IP_URL = 'https://ipinfo.io/json'
const PREFERENCE_URL_PREFIX = 'https://www.example.com/getDomain.php?ip='
const go = async () => {
try {
const { ip } = await (await fetch(IP_URL)).json()
const preference = await fetch(`${PREFERENCE_URL_PREFIX}${ip}`)
//do something with the preference
} catch(err) {
// handle errors
}
}
go()
<script src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Upvotes: 2
Reputation: 4829
There is no promise returned by check_saved_url
nor is $.get returning a promise. You need to wrap it all in a promise
async function check_saved_url() {
return new Promise((resolve, reject) => {
$.get("https://ipinfo.io/json", function (response) {
current_ip = response.ip;
location_here = response.country;
var ajax_get_url_prefix = base_url + 'getDomain.php?ip=';
var key_ip = current_ip + '@@@' + domain_permanent;
var url = ajax_get_url_prefix + key_ip;
$.get(url, function(data, status) {
console.log("Data: " + data + "\nStatus: " + status);
if (data.includes('0 results')) {
resolve('unknown');
} else {
resolve(data);
}
})
.fail(reject);
}, "jsonp")
.fail(reject);
})
}
To have a cleaner and reusable code you can wrap $.get
in a Promise
async function async_get(url) {
return new Promise((resolve, reject) => {
const jqxhr = $.get(url);
jqxhr.done(() => resolve({ json: jqxhr.responseJSON, status: jqxhr.status }));
jqxhr.fail(() => reject(jqxhr));
})
}
async function check_saved_url() {
const { json: response } = await async_get("https://ipinfo.io/json");
current_ip = response.ip;
location_here = response.country;
var ajax_get_url_prefix = base_url + 'getDomain.php?ip=';
var key_ip = current_ip + '@@@' + domain_permanent;
var url = ajax_get_url_prefix + key_ip;
const { json: data, status } = await $.get(url);
console.log("Data: " + data + "\nStatus: " + status);
return data.includes('0 results') ? 'unknown' : data;
}
Upvotes: 1
Reputation: 331
I will suggest you to use fetch API check_saved_url(). It return promise. You can read more about it here. https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
Code will go like this :
async function check_saved_url() {
let connect = await fetch("https://ipinfo.io/json")
let response = await connect.json()
current_ip = response.ip;
location_here = response.country;
var ajax_get_url_prefix = base_url + 'getDomain.php?ip=';
var key_ip = current_ip + '@@@' + domain_permanent;
var url = ajax_get_url_prefix + key_ip;
// $.get(url, function(data, status) {
// console.log("Data: " + data + "\nStatus: " + status);
// if (data.includes('0 results')) {
// return 'unknown';
// } else {
// return data;
// }
// });
// }, "jsonp");
}
Upvotes: 0
Reputation: 2869
You need to return a Promise
from check_saved_url
. Inside of the Promise, you then need to use resolve
to replace return
. You can also use reject(new Error("error"))
if there was an error.
async function check_saved_url() {
return new Promise((resolve, reject) => {
$.get("https://ipinfo.io/json", function (response) {
current_ip = response.ip;
location_here = response.country;
var ajax_get_url_prefix = base_url + 'getDomain.php?ip=';
var key_ip = current_ip + '@@@' + domain_permanent;
var url = ajax_get_url_prefix + key_ip;
$.get(url, function(data, status) {
console.log("Data: " + data + "\nStatus: " + status);
if (data.includes('0 results')) {
// Instead of return, use resolve()
//return 'unknown';
resolve('unknown');
// You can also pass an error with `reject(new Error("error"))`
} else {
// Instead of return, use resolve()
//return data;
resolve(data);
}
});
}, "jsonp");
});
}
const func1 = async() => {
return await check_saved_url();
}
const func2 = async() => {
let domain_preference = '';
domain_preference = await func1();
console.log("domain_preference: ",domain_preference);
}
func2();
You can read more about promises on MDN
Upvotes: 1
Reputation: 1470
Your function check_saved_url
does not return a promise - this is why await
is not working for it.
The solution would be to return a promise in check_saved_url
.
Suppose I have a function create_promise
which I want to await (this mimics your 'get' request):
function create_promise() {
return new Promise(resolve => {
setTimeout(() => resolve("Done!"), 500);
});
}
const func1 = async() => {
const result = await create_promise();
return result + " <- result";
};
func1().then(console.log);
Upvotes: 0