在承诺链上使用 setTimeout

2022-08-30 02:29:36

在这里,我试图把我的头包裹在承诺中。在这里,在第一个请求中,我获取一组链接,在下一个请求中,我获取第一个链接的内容。但是我想在返回下一个承诺对象之前进行延迟。所以我在上面使用setTimeout。但是它给了我以下JSON错误(没有setTimeout(),它工作得很好)

语法错误: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);
});

答案 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 对象,然后直接对您的 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);
});

或者,使用已经内置了该方法的Bluebird promise库.delay()


答案 2
.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))

更新:

当我需要在异步函数中睡觉时,我会投入

await new Promise(resolve => setTimeout(resolve, 1000))