Обещание не возвращать значение запроса

1

У меня есть это обещание:

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" в главной функции никогда не выполняется, и мой код зависает там. Как я могу это исправить? Я не понимаю много обещаний, но я не могу понять, почему это висит...

Теги:
promise
request
tampermonkey
gm-xmlhttprequest

2 ответа

1
Лучший ответ

Я называю это внутри себя, когда ответ не то, что я хочу,

и тогда вы не вызываете 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];
        }
    });
}
  • 0
    Я полагаю, что с вашим ответом вы бы тоже сработали, хотя другой мне было проще реализовать.
  • 0
    Да, это немного больше, чтобы изменить, но более чистое и безопасное решение. Повсеместно используя обещания, вы получаете их преимущества, такие как исправление ошибок и т. Д. Если вам это нравится, вы все равно можете проголосовать, принимая другой ответ :-)
Показать ещё 1 комментарий
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 никогда не отвергает обещание.

  • 0
    Я попытаюсь. В самом деле, вы правы, мне все еще нужно понять, что ловить, потому что когда я получу то, чего не хочу, я хочу позвонить снова, я просто уберу уловку. Теперь я понимаю, что вы имеете в виду, мне нужно было разрешить новый вызов getAPI, поэтому, когда я получу правильный ответ, он будет рекурсивно отправлять решение каждому обещанию, созданному «задом наперед», и, наконец, даст мне желаемый результат. правильно ?
  • 0
    Кстати, это 'setTimeout (doRequest, 5000);' или 'setTimeout (function () {doRequest}, 5000);' ? когда я использую первый случай, иногда получается странное поведение ...
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню