Promesse récursive en javascript
j'écris un Javascript Promise
qui trouve L'URL de redirection finale d'un lien.
ce que je fais c'est faire un HEAD
demande Promise
à l'aide d'un XMLHttpRequest
. Puis, en charge, vérifiez L'état HTTP pour quelque chose dans la gamme 300, ou si elle a un responseURL
attaché à l'objet et cette url est différente de celle qu'il a reçue d'une seule main.
si ni l'un ni l'autre n'est vrai, je resolve(url)
. Sinon, j'appelle récursivement getRedirectUrl()
sur L'URL de la réponse, et resolve()
.
Voici mon code:
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;
}
alors pour utiliser cette fonction je fais quelque chose comme:
getRedirectUrl(myUrl).then(function (url) { ... });
Le problème est que resolve();
getRedirectUrl
appel then()
à partir de la fonction d'appel avant d'appeler le getRedirectUrl
appel récursif, et à ce point, L'URL est undefined
.
j'ai essayé, plutôt que p.then(...getRedirectUrl...)
en faisant return self.getRedirectUrl(...)
mais cela ne résoudra jamais.
mon avis est que le modèle que j'utilise (que je essentiellement venu avec à la volée) n'est pas bonne, tout à fait.
2 réponses
le problème est que la promesse que vous revenez de getRedirectUrl()
doit inclure toute la chaîne logique pour accéder à L'URL. Tu me rends juste une promesse pour la toute première demande. .then()
vous utilisez au milieu de votre fonction ne fait rien.
Pour résoudre ce problème:
Créer une promesse qui résout redirectUrl
pour la redirection, ou rien sinon:
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();
});
Utiliser .then()
pour retourner l'appel récursif, ou pas, en tant que de besoin:
return p.then(function (redirectsTo) {
return redirectsTo
? getRedirectUrl(redirectsTo, redirectCount+ 1)
: url;
});
solution complète:
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;
});
}
veuillez cocher l'exemple ci-dessous il retournera factorial
d'un nombre donné comme nous l'avons fait dans de nombreux langages de programmation.
j'ai implémenté l'exemple suivant en utilisant JavaScript
promesses.
let code = (function(){
let getFactorial = n =>{
return new Promise((resolve,reject)=>{
if(n<=1){
resolve(1);
}
resolve(
getFactorial(n-1).then(fact => {
return fact * n;
})
)
});
}
return {
factorial: function(number){
getFactorial(number).then(
response => console.log(response)
)
}
}
})();
code.factorial(5);
code.factorial(6);
code.factorial(7);