在这里,我试图绕过promises。在第一个请求时,我获取了一组链接。在下一个请求时,我获取了第一个链接的内容。但是我想在返回下一个promise对象之前进行延迟。所以我使用setTimeout上,但是它给了我下面的JSON错误( without setTimeout() it works just fine )
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); });
为了保持承诺链的进行,您不能使用处理setTimeout()的方式,因为您没有从.then()处理程序中返回承诺- 您是从setTimeout()回调中返回承诺的,这对您没有好处。
setTimeout()
.then()
相反,您可以制作一个简单的小延迟函数,如下所示:
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 直接使用一个方法,如下所示:
.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); });
或者,使用已经内置方法的BluebirdPromise库.delay()。
.delay()