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.
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>
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
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;
}