Разрешить обещание по массиву pu sh - javascript - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь определить функцию, которая возвращает обещание. Обещание должно разрешиться, когда заданный массив установлен (push()).

Для этого я пытаюсь использовать объект Proxy (под влиянием this ):

let a = []

;(async function(){

  const observe = array => new Promise(resolve =>
      new Proxy(array, {
          set(array, key, val) {
              array[key] = val;
              resolve();
            }
      }));

  while(true){

      await observe(a);
      console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:",`${a.pop()}`);
    }

})(a);

;(async function(){
    await new Promise(resolve => timerID = setTimeout(resolve, 2000))
    a.push('ʕ·͡ᴥ·ʔ');
    a.push('¯\(°_o)/¯ ')
})(a)

Я не понимаю, почему это не работает. У кого-нибудь есть идеи?

В более общем смысле, Каков хороший способ разрешения обещания на pu sh для массива?

1 Ответ

3 голосов
/ 20 января 2020

Проблемы с вашей попыткой:

  • вы вызываете .push в исходном массиве, а не в прокси. Когда вы создаете прокси, он никому не возвращается: любая ссылка на него теряется (и будет собираться мусором).
  • Код, следующий за строкой с await, будет выполняться асинхронно, поэтому после того, как все ваших push вызовов уже выполнены. Это означает, что console.log будет выполняться, когда массив уже имеет два элемента. Таким образом, обещания не являются подходящим инструментом для того, что вы хотите, так как разрешение обещания может быть выполнено только тогда, когда весь другой синхронный код завершен. Чтобы получать уведомления во время выполнения синхронно , вам необходимо синхронное решение, в то время как обещания основаны на асинхронном выполнении.

Просто для завершения ответа я представьте здесь простое решение для синхронного обратного вызова:

function observed(array, cb) {
    return new Proxy(array, {
        set(array, key, val) {
            array[key] = val;
            if (!isNaN(key)) cb(); // now it is synchronous
            return true;
        }
    });
}

let a = observed([], () =>
    console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:", `${a.pop()}`)
);

a.push('ʕ·͡ᴥ·ʔ');
a.push('¯\(°_o)/¯ ');

Как отмечалось ранее: обещания не являются правильным инструментом, когда вам нужно синхронное выполнение кода.

Когда каждый push выполняется асинхронно

Вы можете использовать обещания, если вы уверены, что каждое push происходит в отдельной задаче, где очередь заданий обещания обрабатывается между каждой парой вызовов push.

Например, если вы делаете каждый push вызов как часть обработчика входного события или как обратный вызов для таймера setTimeout, то это возможно:

function observed(array) {
    let resolve = () => null; // dummy
    let proxy = new Proxy(array, {
        set(array, key, val) {
            array[key] = val;
            if (!isNaN(key)) resolve();
            return true;
        }
    });
    proxy.observe = () => new Promise(r => resolve = r);
    return proxy;
}


let a = observed([]);
(async () => {
    while (true) {
        await a.observe();
        console.log(new Date().toLocaleTimeString(),"Blimey Guv'nor:",`${a.pop()}`);
    }
})();

setTimeout(() => a.push('ʕ·͡ᴥ·ʔ'), 100);
setTimeout(() => a.push('¯\(°_o)/¯ '), 100);
...