【问题标题】:How can I apply a delay to .then promise? [duplicate]我怎样才能延迟 .then 承诺? [复制]
【发布时间】:2019-06-19 19:02:46
【问题描述】:

我有以下功能:

async typewrite(what, where){} - 模拟某人输入文本
async typeerase(where){} - 类似于打字,但模拟某人按下退格键 typetimer(){} - 返回一个 promise,随机间隔来模拟打字速度。

基本上,我想做的是在typewrite 函数完成后,我想在一小段延迟后擦除文本。我尝试使用setTimeout 人为地延迟它,但这似乎不起作用。


以下代码按预期工作

typewrite('Hello world!', target).then(erase => typeerase(target));

let typetimer = (fmin, fmax) => ( 
  new Promise(res => setTimeout(res, Math.floor(Math.random() * (fmax - fmin + 1)) + fmin))
); 

const textarea = document.getElementById('textarea');

async function typewrite(what, where){
  let current_text = '';
  const typespeed_min = 50;
  const typespeed_max = 150;
  
  for (let i = 0; i < what.length; i++){
    await typetimer(typespeed_min, typespeed_max);
    current_text += what.charAt(i);
    where.innerHTML = current_text;
  }
}


async function typeerase(where){
  const erasespeed_min = 30;
  const erasespeed_max = 70;
  let current_text = where.textContent;
  
  while (current_text.length > 0){
    await typetimer(erasespeed_min, erasespeed_max)
    current_text = current_text.substring(0, current_text.length - 1);
    where.innerHTML = current_text;
  }  
}

typewrite('Hello, I am an asynchronous function!', textarea)
  .then(erase => typeerase(textarea));
html {
  font-family: 'Courier New';
  font-weight: bold;
  font-size: 15pt;
}
&lt;p id="textarea"&gt;&lt;/p&gt;

但是,应用人工setTimeout() 延迟似乎根本没有影响。

typewrite('Hello world!', target).then(erase =&gt; setTimeout(typeerase(target), 50000));

let typetimer = (fmin, fmax) => ( 
  new Promise(res => setTimeout(res, Math.floor(Math.random() * (fmax - fmin + 1)) + fmin))
); 

const textarea = document.getElementById('textarea');

async function typewrite(what, where){
  let current_text = '';
  const typespeed_min = 50;
  const typespeed_max = 150;
  
  for (let i = 0; i < what.length; i++){
    await typetimer(typespeed_min, typespeed_max);
    current_text += what.charAt(i);
    where.innerHTML = current_text;
  }
}


async function typeerase(where){
  const erasespeed_min = 30;
  const erasespeed_max = 150;
  let current_text = where.textContent;
  
  while (current_text.length > 0){
    await typetimer(erasespeed_min, erasespeed_max)
    current_text = current_text.substring(0, current_text.length - 1);
    where.innerHTML = current_text;
  }  
}

typewrite('Hello, I am an asynchronous function!', textarea)
  .then(erase => setTimeout(typeerase(textarea), 100000000));
html {
  font-family: 'Courier New';
  font-weight: bold;
  font-size: 15pt;
}
&lt;p id="textarea"&gt;&lt;/p&gt;

看来我在这里几乎错过了一些非常基本/基本的东西,但我似乎无法意识到我在这里做错了什么。

【问题讨论】:

  • setTimeout 接受 函数 作为参数。使用setTimeout(typeerase(target),您不是在传递函数,而是立即调用函数,并传递它的返回值。
  • @CertainPerformance 所以如果我做对了,我基本上应该创建一个额外的 Promise 层,类似于 delay 函数,它返回一个超时承诺,然后才调用 @987654338 @函数,还是有更优雅的方法来实现这一点?

标签: javascript asynchronous promise async-await es6-promise


【解决方案1】:
function delay(ms, resolveWith) {
    return new Promise(resolve=>setTimeout(resolve, ms, resolveWith));
}

typewrite('Hello world!', target)
  .then(erase => delay(5000, erase))
  .then(erase => typeerase(target));

【讨论】:

  • 嗯...为什么不只是setTimeout(resolve, ms, ...args)?另外resolve 只接受一个参数,所以传播是没有意义的。
  • 也许是一个简单的问题,.bind(null, ...args) 背后的原因是什么? this 关键字似乎没有任何用处。
  • @JonasWilms 我认为他的 typewrite 函数在参数中使用名为 erase 的东西来解决。因此,如果他想在延迟之后在.then 中使用它,他需要一种方法来获取下一个.then 回调的erase 参数。我实际上认为resolve 只能用一个参数解决,所以也许我应该将...args 更改为arg
  • 哦@JonasWilms!我不知道setTimeout 比前两个拿了更多的参数,这真的很酷!我通过回答问题学到了一些东西!已更新。
【解决方案2】:

简答:setTimeout 不能这样工作。您应该可以这样做:

typewrite('Hello world!', target)
    .then(erase => setTimeout(() => typeerase(target), 50000));

长答案:您可能应该使用包装 setTimeout 的辅助方法来产生所需的延迟(Noitidart's answer 显示了一个示例)...

typewrite('Hello world!', target)
    .then(() => delay(50000))
    .then(() => typeerase(target));

...然后使用await

await typewrite('Hello world!', target);
await delay(50000);
await typeerase(target);

【讨论】:

  • 感谢兄弟的体育精神! :)
  • :-) 你打赌。良好的团队合作。我仍在试图弄清楚为什么有人对你的答案投了反对票。
  • 他的原始答案有错误(不是我投反对票)
  • 我非常感谢您对 downvvote 的评论,您可能是修复它的赞成票 :) 谢谢!
  • @StriplingWarrior 一个简单的问题,我对你答案的最后部分有点困惑“然后使用await。额外的await 的原因是什么?延迟不会通过简单地应用于.then( () =&gt; delay(ms)); 来起作用吗?
猜你喜欢
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
  • 2011-07-23
  • 2022-12-09
相关资源
最近更新 更多