web-dev-qa-db-fra.com

utiliser setTimeout sur la chaîne de promesse

Ici, je suis en train d'essayer de comprendre les promesses.Voici à la première demande, je vais chercher un ensemble de liens. Et à la prochaine demande, je vais chercher le contenu du premier lien. setTimeout sur it.Mais cela me donne l'erreur JSON suivante (without setTimeout() it works just fine)

SyntaxError: JSON.parse: caractère inattendu à la ligne 1 colonne 1 des données JSON

je voudrais savoir pourquoi il échoue?

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);
});
88
AL-zami

Pour maintenir la chaîne de promesses, vous ne pouvez pas utiliser setTimeout() comme vous le faites parce que vous ne renvoyez pas de promesse du gestionnaire .then(), vous la renvoyez à partir de setTimeout() rappel qui ne vous sert à rien.

Au lieu de cela, vous pouvez créer une simple fonction de délai comme celle-ci:

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

Et puis utilisez-le comme ceci:

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");
    });
});

Ici, vous retournez une promesse du gestionnaire .then() et elle est donc chaînée correctement.


Vous pouvez également ajouter une méthode de délai à l'objet Promise, puis utiliser directement une méthode .delay(x) sur vos promesses, comme suit:

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

Promise.prototype.delay = function(t) {
    return this.then(function(v) {
        return delay(t, v);
    });
}


Promise.resolve("hello").delay(500).then(function(v) {
    console.log(v);
});

Ou bien, utilisez le bibliothèque de promesses Bluebird qui contient déjà la méthode .delay().

152
jfriend00
.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))
61
Igor Korsakov

La version ES6 plus courte de la réponse:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

Et alors tu peux faire:

delay(3000).then(() => console.log('Hello'));
29
Sébastien Rosset

Si vous êtes dans un bloc . Then () et que vous voulez exécuter un settimeout ()

            .then(() => {
                console.log('wait for 10 seconds . . . . ');
                return new Promise(function(resolve, reject) { 
                    setTimeout(() => {
                        console.log('10 seconds Timer expired!!!');
                        resolve();
                    }, 10000)
                });
            })
            .then(() => {
                console.log('promise resolved!!!');

            })

comme indiqué ci-dessous

wait for 10 seconds . . . .
10 seconds Timer expired!!!
promise resolved!!!

Bon codage!

5
AnoopGoudar