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' 永远不会执行,我的代码挂在那里。我该如何解决?我不太了解承诺,但我不明白为什么它会挂起......

4

2 回答 2

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拒绝承诺。

于 2017-10-29T15:39:43.847 回答
1

当答案不是我想要的时候,我把它叫做它本身,

然后你不调用resolve你从顶部getAPI调用返回的承诺,所以承诺永远不会解决,你的then回调永远不会得到任何结果。

您应该在最低级别上承诺您的异步函数GM_xmlhttpRequestsetTimeout然后只链接您的承诺。通过return从回调中获取递归调用的结果then,生成的 Promise 将以相同的结果解析:

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];
        }
    });
}
于 2017-10-29T18:57:20.737 回答