本文介绍了javascript中的递归Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个Javascript Promise ,它会找到链接的最终重定向网址。

I'm writing a Javascript Promise that finds the final redirect URL of a link.

我是什么我正在做的是使用 XMLHttpRequest Promise 中发出 HEAD 请求$ C>。然后,在加载时,检查300状态中的某些内容的HTTP状态,或者它是否附加到该对象的 responseURL ,并且该url与它是单手的不同。

What I'm doing is making a HEAD request in a Promise using an XMLHttpRequest. Then, on load, check the HTTP Status for something in the 300 range, or if it has a responseURL attached to the object and that url is different than the it was one handed.

如果这些都不属实,我 resolve(url)。否则,我在响应URL上递归调用 getRedirectUrl(),并且 resolve()

If neither of these are true, I resolve(url). Otherwise, I recursively call getRedirectUrl() on the response URL, and resolve().

这是我的代码:

function getRedirectUrl(url, maxRedirects) {
    maxRedirects = maxRedirects || 0;
    if (maxRedirects > 10) {
        throw new Error("Redirected too many times.");
    }

    var xhr = new XMLHttpRequest();
    var p = new Promise(function (resolve) {
        xhr.onload = function () {
            var redirectsTo;
            if (this.status < 400 && this.status >= 300) {
                redirectsTo = this.getResponseHeader("Location");
            } else if (this.responseURL && this.responseURL != url) {
                redirectsTo = this.responseURL;
            }

            if (redirectsTo) {
                // check that redirect address doesn't redirect again
                // **problem line**
                p.then(function () { self.getRedirectUrl(redirectsTo, maxRedirects + 1); });
                resolve();
            } else {
                resolve(url);
            }
        }

        xhr.open('HEAD', url, true);
        xhr.send();
    });

    return p;
}

然后使用此功能我会做类似的事情:

Then to use this function I do something like:

getRedirectUrl(myUrl).then(function (url) { ... });

问题在于 resolve(); getRedirectUrl 中,在调用 getRedirectUrl then() / code>递归调用,此时,URL为 undefined

The issue is that resolve(); in getRedirectUrl will call the then() from the calling function before it calls the getRedirectUrl recursive call, and at that point, the URL is undefined.

我试过,而不是 p.then(... getRedirectUrl ...)执行返回self.getRedirectUrl(...)但这永远不会解决。

I tried, rather than p.then(...getRedirectUrl...) doing return self.getRedirectUrl(...) but this will never resolve.

我的猜测是我正在使用的模式(我基本上是想出来的)不完全正确。

My guess is that the pattern I'm using (that I basically came up with on the fly) isn't right, altogether.

推荐答案

问题是你从 getRedirectUrl()返回的承诺需求包括整个逻辑链以获取URL。你只是回复了第一个请求的承诺。你在函数中使用的 .then()没有做任何事情。

The problem is that the promise you return from getRedirectUrl() needs to include the entire chain of logic to get to the URL. You're just returning a promise for the very first request. The .then() you're using in the midst of your function isn't doing anything.

To解决此问题:

为重定向创建一个解析为 redirectUrl 的承诺,否则不执行任何操作:

Create a promise that resolves to redirectUrl for a redirect, or nothing otherwise:

var p = new Promise(function (resolve) {
    var xhr = new XMLHttpRequest();

    xhr.onload = function () {
        var redirectsTo;

        if (xhr.status < 400 && xhr.status >= 300) {
            redirectsTo = xhr.getResponseHeader("Location");
        } else if (xhr.responseURL && xhr.responseURL != url) {
            redirectsTo = xhr.responseURL;
        }

        resolve(redirectsTo);
    };

    xhr.open('HEAD', url, true);
    xhr.send();
});

在 .then() > 根据需要返回递归调用:

Use .then() on that to return the recursive call, or not, as needed:

return p.then(function (redirectsTo) {
    return redirectsTo
        ? getRedirectUrl(redirectsTo, redirectCount+ 1)
        : url;
});

完整解决方案:

function getRedirectUrl(url, redirectCount) {
    redirectCount = redirectCount || 0;
    if (redirectCount > 10) {
        throw new Error("Redirected too many times.");
    }

    return new Promise(function (resolve) {
        var xhr = new XMLHttpRequest();

        xhr.onload = function () {
            var redirectsTo;

            if (xhr.status < 400 && xhr.status >= 300) {
                redirectsTo = xhr.getResponseHeader("Location");
            } else if (xhr.responseURL && xhr.responseURL != url) {
                redirectsTo = xhr.responseURL;
            }

            resolve(redirectsTo);
        };

        xhr.open('HEAD', url, true);
        xhr.send();
    })
    .then(function (redirectsTo) {
        return redirectsTo
            ? getRedirectUrl(redirectsTo, redirectCount+ 1)
            : url;
    });
}

这篇关于javascript中的递归Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 09:22