Usando setTimeout en la cadena de promesa

Resuelto AL-zami asked hace 8 años • 8 respuestas

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);
});
AL-zami avatar Sep 17 '16 01:09 AL-zami
Aceptado

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);
});
Expandir fragmento

jfriend00 avatar Sep 16 '2016 19:09 jfriend00
.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))
Igor Korsakov avatar Nov 01 '2017 13:11 Igor Korsakov