问题描述
我正在编写一个Javascript Promise
,它会找到链接的最终重定向网址。
I'm writing a Javascript Promise
that finds the final redirect URL of a link.
我是什么我正在做的是使用 XMLHttpRequest $ c在
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!