我有一个异步函数,该函数具有一个循环,需要它可以暂停或取消暂停它。这是我到目前为止所拥有的。

我使用一个标志来暂停流程:

let flag = true;

function flag_func() {
    flag = !flag;
}


$(document).ready(function () {
    function sleep(ms) {
        while (!flag) {
            //...waiting.. but infinite loop
        }
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async function show_simulation(data) {
        document.getElementById("solve-button").outerHTML = "<button type=\"button\" id='pause-button' onclick='flag_func()' class=\"btn btn-primary btn-lg\">Pause</button>";
        //simulation
        if (data.length === 0) {
            console.log('stuff')
        } else {
            let i;
            for (i = 0; i < data.length; i++) {
                await sleep(40);
                // do stuff
            }
        }
    }
});


问题是正在暂停,但是由于while阻塞了流程,所以我无法取消暂停for循环。

关于如何解决这个问题的任何想法吗?

最佳答案

对于异步可迭代对象,这可能是一个很好的用例。创建异步列表需要一些样板,但是代码要好得多。基本上,您将拥有:

import AsyncList from './async-list.js'

const sleep = (ms) => new Promise(r => setTimeout(r, ms));

async function f(data) {
  const list = new AsyncList(data);

  document.getElementById("btn-toggle").addEventListener("click", function () {
    if (list.paused) {
      this.textContent = "Pause";
      list.resume();
    } else {
      this.textContent = "Resume";
      list.pause()
    }
  })


  for await (let item of list) {
    console.log(item)
    await sleep(1000);
  }
  console.log("end of loop")
}

f([10, "hello", 1029, 90, 80, 209, 44])


AsyncList的可能实现是:

export default class AsyncList {
  constructor(array) {
    // shallow copy
    this._array = array.slice();

    this._index = 0;
    this._length = this._array.length;
    this.paused = false;
    this._resume = () => {}; // noop, in case `resume` is called before `pause`
  }

  [Symbol.asyncIterator]() {
    return this;
  }

  pause() {
    this.paused = true;
  }

  resume() {
    this.paused = false;
    this._resume();
  }

  next() {
    if (this._index < this._length) {
      const value = this._array[this._index++];

      if (this.paused) {
        return new Promise(r => this._resume = r.bind(null, { value }))
      }

      return Promise.resolve({ value })
    } else {
      return Promise.resolve({ done: true });
    }
  }
}


只是为了给您一个想法,您还可以封装私有属性,并检查更多方案(例如,这里我假设data是一个数组,而不仅仅是一个可迭代的数组)。

关于javascript - 异步函数中的javascript中的暂停和取消暂停循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51412013/

10-13 09:28