0

Consider the following JavaScript Proxy:

const queue = new Proxy([], {

    get: (target, property) => {
        return target[property];
    },

    set: (target, property, value) => {

        target[property] = value;

        this._processQueue();

        return true;

    }

});

The purpose of the above is to create a queue which is automatically processed whenever an item is added to it.

The problem is that once the queue is processed, I need to call flushQueue to remove the processed items. In other words, I need to empty the queue Proxy array.

Can anyone advise how to do this?

What I have tried...

// Can't do this as a) queue is a constant, and b) it overrides the Proxy
queue = [];

// For some reason this doesn't work
queue.length = 0; 

// This empties the array but for some reason does not reset the length...
queue.splice(0, queue.length);

Update

Please see my full example here:

class Foo {

    /**
     * Foo constructor.
     *
     * @return void
     */
    constructor() {

        this.queue = new Proxy([], {

            get: (target, property) => {
                return target[property];
            },

            set: (target, property, value) => {

                this._processQueue();

                target[property] = value;

                return true;

            }

        });

    }

    /**
     * Add an event to the queue.
     *
     * @param {object} event
     * @return void
     */
    _addToQueue(event) {
        this.queue.push(event);
    }

    /**
     * Process the event queue.
     *
     * @return void
     */
    _processQueue() {

        console.log('process queue', this.queue, this.queue.length);

        if (this.queue.length) {

            this.queue.forEach((event, index) => {

                console.log(event);

                const method = this._resolveEvent(event.type);

                const payload = typeof event.payload !== 'undefined' ? event.payload : {};

                //this[method](payload);

            });

            this._flushQueue();

        }

    }

    /**
     * Flush the event queue.
     *
     * @return void
     */
    _flushQueue() {
        this.queue.splice(0, this.queue.length);
    }
}
5
  • Why can't you set it to empty array again ? can you please create a minimum reproducible example ? Commented Oct 29, 2019 at 16:52
  • @CodeManiac - I have posted up my full code with irrelevant bits stripped out. If I run this.queue = []; then it will remove the Proxy and just be a normal array. Or am I wrong? It seemed to do that when I did it before.... Commented Oct 29, 2019 at 16:58
  • Why you're calling this._processQueue(); inside set trap, it seems to create a infinite loop Commented Oct 29, 2019 at 17:12
  • @CodeManiac the reason I am triggering the process method is the whole reason why I have set up the Proxy. Whenever a change is detected on the queue array, the queue should be processed. Essentially I am trying to create a watcher for the queue array and based on what I found online, this seems to be the way to do it. The reason there is an infinite loop is because splice does not seem to be resetting the length of the array when I remove the items, therefore if (this.queue.length) always evaluates to true once an item has been added. Does that make sense? Commented Oct 29, 2019 at 17:28
  • Yeah it makes sense, wasn't able to understand the motive behind using proxy before this comment, the problem is placement of this._processQueue you're calling it before setting the value, whereas you should call it after setting the value Commented Oct 29, 2019 at 17:45

1 Answer 1

1

Problem in your code is you're calling this._processQueue before setting value to target, so it end-up in infinite loop, because it never set the value to target

class Foo {
  constructor() {
    this.queue = new Proxy([], {
      get: (target, property) => {
        return target[property];
      },
      set: (target, property, value) => {
        console.log('set called', value)
        target[property] = value;
        this._processQueue();
        return true;
      }
    });
  }

  _addToQueue(event) {
    this.queue.push(event);
  }

  _processQueue() {
    console.log('process queue', this.queue, this.queue.length);
    if (this.queue.length) {
      this.queue.forEach((event, index) => {
        console.log(event);
        //                 const method = this._resolveEvent(event.type);
        const payload = typeof event.payload !== 'undefined' ? event.payload : {};
        //this[method](payload);
      });
      this._flushQueue();
    }
  }

  _flushQueue() {
    this.queue.splice(0, this.queue.length);
  }
}

const q = new Foo()
q._addToQueue({
  type: 'clcik',
  payload: 'hello'
})
q._processQueue()

Sign up to request clarification or add additional context in comments.

1 Comment

Sorry for the delay. You are absolutely right, I can't believe it was such a basic mistake! Thank you!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.