在promise链上使用setTimeout

AL-*_*ami 97 javascript json promise

在这里,我试图围绕promises.Here在第一次请求我获取一组链接.并在下一个请求我获取第一个链接的内容.但我想在返回下一个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);
});
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 164

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

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

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}
Run Code Online (Sandbox Code Playgroud)

然后,像这样使用它:

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");
    });
});
Run Code Online (Sandbox Code Playgroud)

在这里,您将从.then()处理程序返回一个承诺,因此它被链接得恰当.


您还可以向Promise对象添加延迟方法,然后直接.delay(x)在promises上使用方法,如下所示:

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);
});
Run Code Online (Sandbox Code Playgroud)

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

  • @pdem-“ v”是一个可选值,您希望使用它来解决延迟承诺,并向下传递承诺链。`resolve.bind(null,v)`代替了function(){resolve(v);}`都可以使用。 (4认同)
  • @ AL-zami-`delay()`返回一个将在`setTimeout()`之后解析的承诺。 (2认同)
  • 什么是“ v”,为什么我们需要绑定解析? (2认同)

小智 65

.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))
Run Code Online (Sandbox Code Playgroud)


Séb*_*set 38

更短的ES6版本答案:

const delay = t => new Promise(resolve => setTimeout(resolve, t));
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

delay(3000).then(() => console.log('Hello'));
Run Code Online (Sandbox Code Playgroud)


kig*_*iri 15

从 Node v15 开始,您可以使用计时器 Promise API

文档中的示例:

import { setTimeout } from 'timers/promises'

const res = await setTimeout(100, 'result')

console.log(res)  // Prints 'result'
Run Code Online (Sandbox Code Playgroud)


Ano*_*dar 6

如果您位于.then()块中,并且想要执行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!!!');

            })
Run Code Online (Sandbox Code Playgroud)

输出将如下图所示

wait for 10 seconds . . . .
10 seconds Timer expired!!!
promise resolved!!!
Run Code Online (Sandbox Code Playgroud)

编码愉快!