一尘不染

在承诺链上使用setTimeout

javascript

在这里,我试图绕过promises。在第一个请求时,我获取了一组链接。在下一个请求时,我获取了第一个链接的内容。但是我想在返回下一个promise对象之前进行延迟。所以我使用setTimeout上,但是它给了我下面的JSON错误(
without setTimeout() it works just fine

SyntaxError:JSON.parse:JSON数据的第1行第1列出现意外字符

我想知道为什么会失败?

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

阅读 307

收藏
2020-05-01

共1个答案

一尘不染

为了保持承诺链的进行,您不能使用处理setTimeout()的方式,因为您没有从.then()处理程序中返回承诺-
您是从setTimeout()回调中返回承诺的,这对您没有好处。

相反,您可以制作一个简单的小延迟函数,如下所示:

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

然后,像这样使用它:

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

在这里,您将从.then()处理程序返回一个诺言,因此该诺言已正确链接。


您还可以向Promise对象添加一个delay方法,然后.delay(x)对您的promise 直接使用一个方法,如下所示:

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

});

或者,使用已经内置方法的BluebirdPromise库.delay()

2020-05-01