Проблемы с вашей попыткой:
- вы вызываете
.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);