在承诺链上使用 setTimeout

在这里,我试图理解我的头脑承诺。在这里,对于第一个请求,我获取一组 links.and 对于下一个请求,我获取第一个 link 的内容。但是我想在返回下一个承诺对象之前做一个延迟,所以我对它使用 setTimeout。但是它给出了下面的 JSON 错误(without setTimeout() it works just fine)

第1行第1列的意外字符 JSON 数据

我想知道为什么会失败?

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);
});
241757 次浏览

为了保持承诺链的正常运行,您不能像以前那样使用 setTimeout(),因为您没有从 .then()处理程序返回承诺——而是从 setTimeout()回调函数返回承诺,这对您没有任何好处。

相反,你可以像下面这样做一个简单的延迟函数:

function delay(t, v) {
return new Promise(resolve => setTimeout(resolve, t, v));
}

然后,像这样使用它:

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(resolve => setTimeout(resolve, t, v));
}


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

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

更新:

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

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

如果您位于 。然后()块内,并且希望执行 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!!!');


})

输出将如下所示

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

编码愉快!

简短的 ES6版本的答案是:

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

然后你可以做:

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

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

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


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

从节点 v15开始,您可以使用 计时器承诺 API

来自文件的例子:

import { setTimeout } from 'timers/promises'


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


console.log(res)  // Prints 'result'
const myStuff = new Promise(function (resolve) {
console.log("before timeout");
setTimeout(
function (x) {
console.log("inside the timeout");
resolve(x);
},
3000,
"after timeout"
);
}).then((response) => console.log(response));

对于当前的 LTS 更容易,我们可以使用异步/等待来处理超时。请注意,这是目前推荐的使用超时的方法。

建议不要使用启用。

const { promisify } = require('util')
const sleep = promisify(setTimeout)
async function myFunction() {
await sleep(1e3)
console.log('This will be seen after 1 sec')
await sleep(5e3)
console.log('This will be seen after 5 sec after')
}