У меня есть это обещание:
function getAPI(token)
{
return new Promise((resolve, reject) => {
console.log("Request API");
GM_xmlhttpRequest({
method: "GET",
url: "URL"+token,
onload: function(response) {
console.log(response.responseText);
if( response.responseText == "NOT_ANSWER" || response.responseText.indexOf("ERRO") > -1 ){
console.log(response.responseText + " - Calling Myself in 5 Seconds");
setTimeout(function(){
getAPI(token);
},5000);
}
else{
console.log('Call API - Giving Result');
resolve(response.responseText.split("_")[1]);
}
}
});
});
}
Я называю это внутри себя, когда ответ не тот, который я хочу, но не может быть меньше 5 секунд.
Затем я делаю это в основной функции:
setTimeout( function(){
getAPI(token).then((key) => {
console.log(key);
doSomethingWithKey;
setTimeout( function(){
loop();
},1000);
}).catch(() => {
console.log('Error na api - reload page!');
location.reload();
});
},25000);
Но я заметил, что когда getAPI вызывает саму себя, потому что ответ - это не то, что я хочу, ".then" в главной функции никогда не выполняется, и мой код зависает там. Как я могу это исправить? Я не понимаю много обещаний, но я не могу понять, почему это висит...
Я называю это внутри себя, когда ответ не то, что я хочу,
и тогда вы не вызываете resolve
обещания, которые вы вернувшиеся из верхней getAPI
вызова, так что обещание никогда не оседает и ваш, then
обратный вызов не получает какой - либо результата.
Вы должны обезопасить свои асинхронные функции GM_xmlhttpRequest
и setTimeout
на самом низком уровне, а затем только GM_xmlhttpRequest
свои обещания. return
результат рекурсивного вызова из then
обратного вызова, получившееся обещание разрешится с тем же результатом:
function xhrAsync(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: resolve
});
});
}
function delayAsync(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
function getAPI(token) {
console.log("Request API");
return xhrAsync("URL"+token).then(response => {
// ^^^^^^ ^^^^
console.log(response.responseText);
if (response.responseText == "NOT_ANSWER" || response.responseText.includes("ERRO")) {
console.log(response.responseText + " - Calling Myself in 5 Seconds");
return delayAsync(5000).then(() => {
// ^^^^^^ ^^^^
return getAPI(token);
// ^^^^^^
});
} else {
console.log('Call API - Giving Result');
return response.responseText.split("_")[1];
}
});
}
Вы создаете несколько обещаний, потому что каждый вызов getAPI
создает и возвращает новое обещание.
getAPI
не должен называть себя (или, если это так, он должен передать новое обещание в resolve
); вместо этого просто повторите часть внутри нее, которую вам нужно повторить, что-то вроде этого:
function getAPI(token) {
return new Promise((resolve, reject) => {
// Function to do the request
function doRequest() {
console.log("Request API");
GM_xmlhttpRequest({
method: "GET",
url: "URL" + token,
onload: function(response) {
console.log(response.responseText);
if (response.responseText == "NOT_ANSWER" || response.responseText.indexOf("ERRO") > -1) {
// Not what we wanted, retry
console.log(response.responseText + " - Calling Myself in 5 Seconds");
setTimeout(doRequest, 5000);
}
else {
console.log('Call API - Giving Result');
resolve(response.responseText.split("_")[1]);
}
}
});
}
doRequest();
});
}
Замечание: ваш код с использованием getAPI
проверяет отказ от обещаний, но ничто в getAPI
никогда не отвергает обещание.