Javascript 在承诺链上使用 setTimeout

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39538473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:40:16  来源:igfitidea点击:

using setTimeout on promise chain

javascriptjsonpromise

提问by AL-zami

Here i am trying to wrap my head around promises.Here on first request i fetch a set of links.and on next request i fetch the content of first link.But i want to make a delay before returning next promise object.So i use setTimeout on it.But it gives me the following JSON error (without setTimeout() it works just fine)

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

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

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

i would like to know why it fails?

我想知道为什么会失败?

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

回答by jfriend00

To keep the promise chain going, you can't use setTimeout()the way you did because you aren't returning a promise from the .then()handler - you're returning it from the setTimeout()callback which does you no good.

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

Instead, you can make a simple little delay function like this:

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

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

And, then use it like this:

然后像这样使用它:

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

Here you're returning a promise from the .then()handler and thus it is chained appropriately.

在这里,您从.then()处理程序返回一个承诺,因此它被适当地链接起来。



You can also add a delay method to the Promise object and then directly use a .delay(x)method on your promises like this:

您还可以向 Promise 对象添加一个延迟方法,然后直接.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);
});

Or, use the Bluebird promise librarywhich already has the .delay()method built-in.

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

回答by Igor Korsakov

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

UPDATE:

更新:

when I need sleep in async function I throw in

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

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

回答by Sébastien Rosset

The shorter ES6 version of the answer:

较短的 ES6 版本的答案:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

And then you can do:

然后你可以这样做:

delay(3000).then(() => console.log('Hello'));

回答by AnoopGoudar

If you are inside a .then()block and you want to execute a settimeout()

如果您在.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!!!');

            })

output will as shown below

输出将如下所示

wait for 10 seconds . . . .
10 seconds Timer expired!!!
promise resolved!!!

Happy Coding!

快乐编码!

回答by Jan

In node.js you can also do the following:

在 node.js 中,您还可以执行以下操作:

const { promisify } = require('util')
const delay = promisify(setTimeout)

delay(1000).then(() => console.log('hello'))