【问题标题】:Is it possible continue a paused async function? (2)是否可以继续暂停的异步功能? (2)
【发布时间】:2017-12-07 12:39:03
【问题描述】:

我对之前的代码进行了一些更改,运行了更多测试,但我又遇到了同样的问题 (Is it possible continue a stopped async function?)。所以这个问题是相关的。

另外,之前的解决方法也行不通。

var stop = false;
var pause = false;
var elParrafo = document.getElementById('miParrafo');

function sendPause() {
  pause = true;
}

function sendContinue() {
  pause = false;
}

function sendStop() {
  stop = true;
}

function longWork(ms, char) {
  return new Promise(function(resolve, reject) {
    elParrafo.innerHTML += char;
    setTimeout(resolve, ms);
  });
}

async function doIt() {
  for (var i = 0; i < 666; i++) {
    if (!stop) {
      if (!pause) {
        await longWork(50," > ");
      }
    } else {
      break;
    }
  }
}

doIt();
<form class="" action="index.html" method="post">
  <input type="button" value="Pause" onclick="sendPause()">
  <input type="button" value="Continue" onclick="sendContinue()">
  <input type="button" value="Stop" onclick="sendStop()">
</form>
<p id="miParrafo"></p>

【问题讨论】:

  • 我不确定你是否理解 Promise 或 async await。使用setTimeoutsetInterval 可以更简单地完成您发布的代码。如果你有长时间运行的代码会阻塞你的 UI,那么你应该使用网络工作者。关于为什么以及如何承诺的信息:stackoverflow.com/a/47678417/1641941

标签: javascript promise async-await


【解决方案1】:

当你暂停任务时,你必须真正暂停它并等到用户想要继续,而不是继续你的循环直到结束,但不做任何工作。

var stopped;
var paused;
var waitingContinuations;

function sendStart() {
  stopped = false;
  paused = false;
  waitingContinuations = [];
  doIt();
}

function sendPause() {
  paused = true;
}

function sendContinue() {
  paused = false;
  for (const cont of waitingContinuations)
    cont();
  waitingContinuations.length = 0;
}

function sendStop() {
  stopped = true;
}

async function doIt() {
  document.getElementById('output').textContent = "";
  for (var i = 0; i < 666; i++) {
    // in places where you might want to abort, put this:
    if (stopped) return; // or throw new Error("stopped");
    // in places where you might want to pause, put this:
    if (paused) await new Promise(resolve => waitingContinuations.push(resolve));

    await longWork(50, " > ");
  }
}

function longWork(ms, char) {
  return new Promise(resolve => {
    document.getElementById('output').textContent += char;
    setTimeout(resolve, ms);
  });
}
<form>
  <input type="button" value="Start" onclick="sendStart()">
  <input type="button" value="Pause" onclick="sendPause()">
  <input type="button" value="Continue" onclick="sendContinue()">
  <input type="button" value="Stop" onclick="sendStop()">
</form>
<p id="output"></p>

【讨论】:

  • new Promise(resolve =&gt; waitingContinuations.push(resolve)); 没有箭头语法的这一行如何等效?
  • 那么,return 可以在没有resolverejectPromise 中使用吗?为什么?
  • 异步发生的return 是没用的——所以我认为你的答案是
  • 所以new Promise(function (resolve) { return waitingContinuations.push(resolve); });Promise 中使用return。你是怎么解释的?
【解决方案2】:

当您将标志设置为 true 时会出现此问题。当您取消设置标志时,异步代码会耗尽循环的其余部分。你可以通过一些承诺来解决它。

let stop = false;
let isPaused = false;
let resolvePause = () => {};
let pauseProm = Promise.resolve();
const elParrafo = document.getElementById('miParrafo');

function sendPause() {
  if(isPaused) return;

  isPaused = true;
  pauseProm = new Promise(resolve => resolvePause = resolve);
}

function sendContinue() {
  isPaused = false;
  resolvePause();
}

function sendStop() {
  stop = true;
}

function longWork(ms, char) {
  return new Promise(function(resolve, reject) {
    elParrafo.innerHTML += char;
    setTimeout(resolve, ms);
  });
}

async function doIt() {
  for (let i = 0; i < 666; i++) {
    if (stop) break;

    await pauseProm;
    await longWork(50," > ");
  }
}

doIt();
<form class="" action="index.html" method="post">
  <input type="button" value="Pause" onclick="sendPause()">
  <input type="button" value="Continue" onclick="sendContinue()">
  <input type="button" value="Stop" onclick="sendStop()">
</form>
<p id="miParrafo"></p>

【讨论】:

  • @kamoroso94 这行到底是做什么的:new Promise(resolve =&gt; resolvePause = resolve); 可以在没有resolvereject 的情况下在promise 中返回?
  • @kamoroso94 你能解释一下sendPause()sendContinue() 的工作原理吗?
【解决方案3】:

这是一个使用 setInterval 的简单解决方案:

var task = (function(){
  var timer;
  var taskImplementation;
  var max;
  var ms;
  var timesRun = 0;
  var isPaused = false;
  const runTask = function(){
    if(!isPaused && timesRun<max){
      taskImplementation();
      timesRun++;
    }else{
      clearInterval(timer);
    }
  };
  const reset = function() {
    timesRun=0;
    isPaused=false;    
  };
  const start = function(){
    if(timer){
      stop();
    }
    reset();
    timer = setInterval(runTask,ms);
  };
  const stop = function(){
    reset();
    clearInterval(timer);
  };
  const pause = function(){
    clearTimeout(timer);
  };
  const cont = function(){
    timer = setInterval(runTask,ms);    
  };
  return function(doWhat){
    taskImplementation = doWhat;
    return function(interval){
      ms = interval;
      return function(howManyTimes){
        max = howManyTimes;        
        return {
          start:start,
          stop:stop,
          pause:pause,
          continue:cont
        }
      }
    }
  }
})();
var doWhat = (function(elParrafo){
  return function(){
    elParrafo.innerHTML += " > ";
  }
})(document.getElementById('miParrafo'));
var interval =200;//how long to wait between task execution
var howManyTimes = 666;//how many times to repeat task
window.setParrafoTask = task(doWhat)(interval)(howManyTimes);
    <form class="" action="index.html" method="post">
        <input type="button" value="Start" onclick="setParrafoTask.start()">
        <input type="button" value="Pause" onclick="setParrafoTask.pause()">
        <input type="button" value="Continue" onclick="setParrafoTask.continue()">
        <input type="button" value="Stop" onclick="setParrafoTask.stop()">
      </form>
      <p id="miParrafo"></p>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 2021-07-21
    • 2014-08-22
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    相关资源
    最近更新 更多