javascript 如何等待数组长度变为指定值?

3xiyfsfu  于 2023-06-04  发布在  Java
关注(0)|答案(3)|浏览(318)

我可以等待一个数组长度改变为JS中指定的值。
例如:
假设这里有一个名为foo的魔术函数,我可以像这样使用foo

async funtion bar () {
    let arr = [];
    // Wait for the arr.length to change to 10, then invoke the handler
    let result = await foo(arr, 10, handler); 
    return result;
}

我的意思是,当arr.length更改为1,2,3... 6,7,8或9...时,只需在这一行等待:let result = await foo(arr, 10, handler);并且不返回result
当arr.length变为10时,调用handler函数,返回result
有谁知道foo这个函数怎么写?或者为什么不能写这个函数?谢谢
我真正想知道的是
我们可以使用await来等待一些异步操作的结果,比如setInterval或者 AJAX ,但是如果我想等待一个“set operation”的指定值(set operations:如proxy中的set,或Object.defineProperty中的setter)。
并注意:
我想知道如果我想“等待”一个指定的集合操作,而不是仅仅“监视”一个指定的集合操作,我应该做什么
例如,当arr.length为0,1,2...9时保持等待,当arr.length为10时执行某些操作

ecbunoof

ecbunoof1#

您可以使用Proxy使用set trap跟踪对阵列的更改。对于每个set运行一个check,如果check返回true,则以数组作为参数运行回调函数(cb):

function trackArray(array, check, cb) {
  const arrayChangeHandler = {
    set: function(target, property, value, receiver) {
      target[property] = value;
      // for every set action, run check with the property (length in this case), and the current value
      check(property, value) && cb(target);
      return true;
    }
  };
  
  return new Proxy(array, arrayChangeHandler);
}

const trackedArray = trackArray(
  [], 
  (property, value) => property === 'length' && value === 10, 
  (arr) => console.log(arr)
);

trackedArray.push(1);
trackedArray.push(2);
trackedArray.push(3);
trackedArray.push(4);
trackedArray.push(5);
trackedArray.push(6);
trackedArray.push(7);
trackedArray.push(8);
trackedArray.push(9);
trackedArray.push(10); // this push will invoke the CB
trackedArray.push(11);
trackedArray.push(12);
trackedArray.pop();
trackedArray.pop(); // this pop will invoke the CB
ghhaqwfi

ghhaqwfi2#

你能检查这个https://jsfiddle.net/j1kd714y/3/
resolveAfter2Seconds像您的foo

function resolveAfter2Seconds(arr, len) {
  return new Promise(resolve => {
    var x = setInterval(() => {
        arr.push(Math.random())
      if(arr.length >= len) {
        clearInterval(x)
        resolve(arr.length);
      }
    }, 500);
  });
}
igsr9ssn

igsr9ssn3#

我最近遇到了类似的情况。我使用数组进行输入队列。我使用setImmediate来解决我的问题:

const unblock = () => new Promise(setImmediate)

const take = async arr => {
  while (true) {
    if (arr.length > 0) return arr.shift()
    else await unblock()
  }
}

我会在这样的函数中使用它们:

const asyncInputOutput = (src, trg) => async () => {
  while (true) {

    // do stuff ...

    if (/* need input */) {
      const data = await take(src)
    }
    if (/* produce output */) {
      trg.push(someData)
    }
  }
}

然后,像这样使用该函数:

const main = async () => {
  const reg = { a: [], b: [], c: [] }

  const machine1 = asyncInputOutput(reg.a, reg.b)
  const machine2 = asyncInputOutput(reg.b, reg.c)

  await Promise.all([machine1(), machine2()])

  return reg.c // or whatever
}

这是2019年Advent of Code挑战赛期间的Intcode。给定一组指令(作为整数),机器可以进行简单的算术运算,最终得到类似cli text game的结果。开门见山地说,多台机器运行会有一个问题,因为如果一台机器的输入队列为空,它就必须暂停。
为了回答你的具体问题,像这样的东西可能会起作用:

const unblock = () => new Promise(setImmediate)

const waitForLength = async (arr, len, handler) => {
  while (true) {
    if (arr.length >= len) return handler(arr)
    else await unblock()
  }
}

const asyncDoThings = async () => {
  const arr = []

  // ... do things

  const result = await waitForLength(arr, 10, handler)
  return result
}

相关问题