等待使用settimeout的函数在javascript中完成后再重新运行

Wait for function that makes use of settimeout to complete in javascript before rerunning it

本文关键字:重新运行 javascript settimeout 函数 等待      更新时间:2023-09-26

请协助。

在用javascript再次执行操作之前,我需要wait来完成操作。这些操作可能在不同的时间运行。不是一次全部。我对同时运行两个操作有问题,因为它们同时执行。

输出应使用settimeout在"文本区域"中附加文本。它需要等待完成,然后开始在调用"arrayofrandomtext"数组的任何随机索引处键入下一个文本。稍后,"ProcessText(someint)"仍可能基于按键等调用

  • 必须追加现有文本,而不是在0处替换,而是追加即Hello World。其他

var index=0;
var arrayofrandomtext = ["Hello World","something else", "other stuff"];
   
   function ProcessText(someint){
   
  //These may run together
  next_letter(arrayofrandomtext[someint]);
  //wait to complete and rerun it with other text
  next_letter(arrayofrandomtext[someint]);
  //later on if the user hits a key this may run only
  next_letter(arrayofrandomtext[someint]);
}
function next_letter(text){
  if (index <= text.length) {
    someControl.value = text.substr(0, index++);
    setTimeout(function () { next_letter(text); }, 50);
 }
}

首先,您已经完成了这项工作,但我想要一个可供演示的工作版本。您可以编写一个递归函数,它在完成后调用settimeout。例如,给定一个函数,该函数注销字符串中的每个字母。

var log = function(text, index, duration) {
  console.log(text[index]);
  if (index < text.length - 1) {
    setTimeout(function() {
      log(text, index + 1, duration);
    }, duration);
  }
};
log("Hello There", 0, 1000);
log("Nice to see You", 0, 1000);

当然,如果您运行此代码,第二个日志函数将不会等待第一个。您可以使用Promises和/或Callback来执行异步控制流。首先修改log函数,将回调作为参数。

var logCB = function(text, index, duration, cb) {
  console.log(text[index]);
  if (index < text.length - 1) {
    setTimeout(function() {
      logCB(text, index + 1, duration, cb);
    }, duration);
  } else {
    cb();  //execute callback
  }
};

现在,如果您传递第二个函数(封装在另一个函数中以延迟执行)。作为第一个的参数,它将在完成后执行。

var cb = function() {
  logCB("Nice to see you", 0, 1000);
};
logCB("Hello, World!", 0, 1000, cb);

虽然这是有效的,但对于多个嵌套来说,它可能会变得很难处理。一个更好的解决方案是使用promise——您只需要将logCB封装在另一个函数中。这里f是一个logCB。

var promiseLog = function(f, text, delay) {
  return new Promise(function(resolve, reject) {
     f(text, 0, delay, resolve);
  });
};

然后。。。我们可以把它们串在一起等待完成。。然后

promiseLog(logCB, "Hello World", 1000)
 .then(function() {
   return promiseLog(logCB, "Hey There", 1000)
 });

尝试创建一个文本值数组,使用Array.prototype.slice()创建文本值初始数组的副本;Array.prototype.shift()next_letter设置文本参数;如果数组在对next_letter的初始调用后具有.length,则递归调用ProcessText

var arr = ["Hello...", "Some other text"],
  copy = arr.slice(),
  button = document.querySelector("input")
  someControl = document.querySelector("textarea"),
  index = 0;
function ProcessText() {
  next_letter(copy.shift())
}
function next_letter(text) {
  if (index <= text.length) {
    someControl.value = text.substr(0, index++);
    setTimeout(function() {
      next_letter(text);
    }, 50);
  } else {
    index = 0;
    if (!!copy.length) {
      ProcessText()
    } else {
      copy = arr.slice();
    }
  }
}
button.onclick = ProcessText;
<input type="button" value="click" /><br />
<textarea></textarea>