2016-09-16 39 views
35

在这里,我试图围绕promise承担我的头。在第一次请求时,我获取一组links.and下一个请求我获取第一个链接的内容。但是我想在返回下一个承诺object.So我上它。但是它给了我下面的JSON错误(without setTimeout() it works just fine在承诺链上使用setTimeout

SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

我想知道为什么它没有使用的setTimeout?

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

请注意,'return'是函数特有的,只返回父函数,并且不能从异步方法返回。 – adeneo

+1

注意有很多[更好的方法](http://stackoverflow.com/q/28250680/1048572)来构造这个代码,而不是使用'globalObj'。 – Bergi

+0

'JSON.parse'扔在哪里?我很难相信在一个“then”回调中是否存在'setTimeout'会影响前一个'then'回调中的调用。 – Bergi

回答

68

要守信链去,你不能使用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()处理程序返回一个承诺因此它被适当地链接。


您也可以延迟方法添加到无极对象,然后直接使用.delay(x)方法对您的承诺是这样的:

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

或者,使用Bluebird promise library这已经有内置的.delay()方法。

+0

解析函数是then()中的函数,所以setTimeout(resolve,t)意味着setTimeout(function(){return ....},t)是不是......那么为什么它会起作用? –

+0

@ AL-zami - 'delay()'返回一个在'setTimeout()'后面解析的promise。 – jfriend00

+0

我已经为setTimeout创建了一个promise包装来轻松地延迟承诺。 https://github.com/zengfenfei/delay – Kevin

8
.then(() => new Promise((resolve) => setTimeout(resolve, 15000))) 
+8

请详细说明为什么这比已经接受的答案更好。如果你不添加任何东西,不要回答。 – klutt

+3

喜欢它!很好,很短! –