Usando setTimeout en la cadena de promesa
Aquí estoy tratando de entender las promesas. Aquí, en la primera solicitud, obtengo un conjunto de enlaces, y en la siguiente solicitud, busco el contenido del primer enlace, pero quiero hacer un retraso antes de devolver el siguiente objeto de promesa, así que uso establezca Timeout en él. Pero me da el siguiente error JSON ( without setTimeout() it works just fine
)
SyntaxError: JSON.parse: carácter inesperado en la línea 1, columna 1 de los datos JSON
¿Me gustaría saber por qué falla?
let globalObj={};
function getLinks(url){
return new Promise(function(resolve,reject){
let http = new XMLHttpRequest();
http.onreadystatechange = function(){
if(http.readyState == 4){
if(http.status == 200){
resolve(http.response);
}else{
reject(new Error());
}
}
}
http.open("GET",url,true);
http.send();
});
}
getLinks('links.txt').then(function(links){
let all_links = (JSON.parse(links));
globalObj=all_links;
return getLinks(globalObj["one"]+".txt");
}).then(function(topic){
writeToBody(topic);
setTimeout(function(){
return getLinks(globalObj["two"]+".txt"); // without setTimeout it works fine
},1000);
});
Para mantener la cadena de promesa en funcionamiento, no puede usar setTimeout()
la forma en que lo hizo porque no está devolviendo una promesa del .then()
controlador; la está devolviendo desde la devolución de setTimeout()
llamada, lo que no le sirve de nada.
En su lugar, puedes crear una pequeña función de retardo como esta:
function delay(t, val) {
return new Promise(resolve => setTimeout(resolve, t, val));
}
Y luego úselo así:
getLinks('links.txt').then(function(links){
let all_links = (JSON.parse(links));
globalObj=all_links;
return getLinks(globalObj["one"]+".txt");
}).then(function(topic){
writeToBody(topic);
// return a promise here that will be chained to prior promise
return delay(1000).then(function() {
return getLinks(globalObj["two"]+".txt");
});
});
Aquí estás devolviendo una promesa del .then()
controlador y, por lo tanto, está encadenada adecuadamente.
También puedes agregar un método de retraso al objeto Promise y luego usar directamente un .delay(x)
método en tus promesas como este:
function delay(t, val) {
return new Promise(resolve => setTimeout(resolve, t, val));
}
Promise.prototype.delay = function(t) {
return this.then(function(val) {
return delay(t, val);
});
}
Promise.resolve("hello").delay(500).then(function(val) {
console.log(val);
});
.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))
ACTUALIZAR:
cuando necesito dormir en la función asíncrona, la incluyo
await new Promise(resolve => setTimeout(resolve, 1000))