JavaScript proxy feature: combining notifications after sorting an array

Seeking a solution to receive only one notification after sorting an array.

Is there a method that accomplishes this? Thank you!

const callback = function () {
  console.log (...arguments)
}
const array = [2,1]
const handler = {
  set (target, prop, value, receiver) {
    callback (prop, value)
    return Reflect.set (target, prop, value, receiver)
  }
}
const proxy = new Proxy (array, handler)
proxy.sort()
// triggers callback twice
// outputs "0" 1 and "0" 2
// hoping for a single notification: "array sorted"

Answer №1

An effective method that avoids using a proxy involves using a general implementation of an around method-modifier. This can be viewed as a specialized form of function wrapping.

This modifier takes two functions, proceed and handler, along with a target-object as its three parameters. It then generates a function that will return the result of the handler function. The handler function is executed within the context of the (possibly) provided target, receiving both the proceed function and its own reference as well as the arguments array of the modified function.

Using this modifier, the OP could achieve the desired outcome by modifying, for example, the sort method of an array instance like so...

const arr = [2, 1];

// assigning the specifically modified `sort` of the array instance.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);

... where notifyAboutFinishedTask represents the handler function that fulfills the requirements outlined by the OP...

"... only one notification after an array sort"

... Sample code ...

// Implementation of `sort`-specific `around` handler.
function notifyAboutFinishedTask(proceed, handler, args) {
  const arr = this;

  // Original task execution.
  proceed.apply(arr, args);

  // Additional notification.
  console.log('\narray sorted');
  console.log('arr ...', arr);
  console.log('arguments ...', args);
}
const arr = [2, 1];

console.log('unsorted arr ...', arr);

// Assigning the specifically modified `sort` of the array instance.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);

// Sorting the array twice, once with a sort function and once without.
arr.sort();
arr.sort((a, b) => b - a);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>

// Implementation of an `around` modifier.
function around(proceed, handler, target) {
  return function (...args) {

    return handler.call(target ?? null, proceed, handler, args);
  };
}

</script>

Answer №2

If you want to apply a custom function to the Array#sort(), you can use the .apply() trap:

console.config({ maximize: true });

Array.prototype.sort = new Proxy(Array.prototype.sort, {
  apply(target, thisArg, argumentList) {
    const sortedThis = Reflect.apply(target, thisArg, argumentList);
    console.log('sorted');
    return sortedThis;
  }
});

console.log([2, 1].sort());
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

To have the proxy impact only your array, you can customize the behavior for the 'sort' property:

console.config({ maximize: true });

const proxy = new Proxy([2, 1], {
  get(target, property, receiver) {
    if (property === 'sort') {
      return function(comparer) {
        const originalSort = Reflect.get(target, property, receiver);
        const sortedThis = originalSort.apply(target, [comparer]);
        
        console.log('sorted');
        
        return sortedThis;
      }
    }
    
    return Reflect.get(target, property, receiver);
  }
});

console.log('.sort() works:', proxy.sort());
console.log('.slice() is fine too:', proxy.slice(1));
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Avoiding ContentPlaceHolder in the creation of ID tags

Recently, I successfully integrated a master page to manage all my sub pages in an older project. In order for the sub pages to render correctly, I had to insert <asp:content id="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server"> i ...

Differences in Angular 2 Performance: Analyzing AOT and JIT Payloads

I'm still getting the hang of Angular 2, so feel free to correct me if I'm off base. Comparing Angular 1 and 2 in terms of the compiler: In Angular 1, the compiler is more general and dynamic, meaning that a single code is used for dirty checki ...

Highlighting table rows when hovering in IE with JQuery - compatibility across all versions

I have a table on my jsp page with multiple rows and columns. I want to ensure that visitors can easily follow along when they interact with the table - by highlighting the row or column they hover over with a different background color. Although the **hov ...

Changing route patterns in NextJS

When deploying a new NextJS app, it is important to preserve legacy routes from the old non-NextJS site. The current setup uses /const-string-[long-unique-hash] for an httpd conf redirect: For example: RewriteRule ^const-string-(.*)$ https://google.com?q ...

Tips for bringing in an npm package in JavaScript stimulus

Looking to utilize the imageToZ64() function within the zpl-image module. After installing it with: npm install zpl-image I attempted importing it using: import './../../../node_modules/zpl-image'; However, when trying to use the function like ...

ReactJS - Unable to access property of undefined object

I encountered a TypeError when rendering, stating that my object is not defined. Despite thinking I defined it before using it. Here is an example of ArticleDetails.js that I am referencing: import React, {Component} from 'react'; class Arti ...

Once the PHP page loads, it becomes challenging for me to dynamically change values in JavaScript

Within my code snippet below, I am aiming to modify the initial value using a slider. The slider appears to be functioning correctly; however, it is not updating the values of timeout as indicated beneath the line $('ul.<?php echo $this->session ...

JavaScript function for converting timestamp to readable date

Can someone help me transform the timestamp 1382086394000 into a readable date format 2013-10-18 08:53:14 by using a JavaScript function? The current function I have is: function cleanDate(d) {return new Date(+d.replace(/\/Date\((\d+)\ ...

What could be the reason for the absence of this retrieved data in my HTML code?

I have a situation where I am retrieving data from a Parse database and showing it on my template: JavaScript Code: angular.module('yoApp') .controller('downloadsCtrl', function($q, $scope, $rootScope, $http, appService, serviceUplo ...

Struggling to integrate CKEditor into my Angular project, as I keep encountering the error message "CKEDITOR is not

These are the steps I followed: 1) To begin, I added the ng-ckeditor.min.js file to my project. 2) Next, I included it in the page using the following code: <script type="text/javascript" src="Scripts/ng-ckeditor.min.js"></script> 3) I then ...

Issue with AngularJS promise not returning any value in JavaScript

I have been attempting to perform a simple HTTP post in a unit test using Jasmine, but unfortunately, it is not functioning as expected. The application operates smoothly on the web, and I have individually tested various functions, all of which work seaml ...

The Skeleton-Avatar and ImageButton components in MUI React have had their backgrounds reshaped into perfect ovals

I am facing an issue with the mui Stack where all the background shapes of the Skeleton Avatar and background area are turning into oval or ellipsoid shapes. I have tried setting equal width and height for Avatar but it has not solved the problem. Is ther ...

instructions for resetting all static array elements to 0 in C

The way I have defined a static array in C is by using the following structure: typedef struct { int a; int b; int c; int d; } Hello; static Hello hello[6] = {{0}}; There are certain points where I need to reset all the values of each element in this st ...

Updates to $scope are not reflecting in the application

My input includes a datalist that is populated by an angular get request as the page loads. <input list="data" /> <datalist id="data"> <option ng-repeat="item in items" value="{{item.data}}"> </datalist> The $http call is straig ...

Can you explain the sequence of steps involved in setting up a server in node.js?

I'm curious about the order in which instructions are executed in this code. Specifically, I want to know if http.createServer() or server.listen is executed first, and when the callback function inside createserver will execute. const http = require( ...

Issues with embedding iframes

I have a webpage with an embedded iframe that is making ajax requests. However, when I click on a link, it opens in the iframe instead of the main window. I tried using this JavaScript code: window.parent.location.href = url of link but it didn't wo ...

Issue with Vue.js app display within Chrome extension

I have encountered an issue while trying to run a Vuejs app in a Chrome extension as a new tab. The app renders perfectly fine when running it from the dist/ folder using simplehttpserver dist/. However, when I attempt to load the dist folder as a Chrome E ...

Using jQuery's .text() function transforms my h1 element into regular text once a number is inputted

I am facing an issue with the following code snippet: <li id="machine" ><h1>Machine</h1></li> <li id="player"><h1>Player</h1></li> It displays as shown in the image below: https://i.sstatic.net/CR3Ut.png ...

When a form added by jQuery is submitted, the associated JavaScript does not run as expected

After clicking a button on my page, jQuery removes one form and replaces it with another. However, when I try to submit the second form, the associated JavaScript does not execute as expected. Instead of running the JavaScript function, the form submissio ...

Guide on setting up a MEAN stack application to run on port 8080

I am brand new to the mean stack development environment. I'm attempting to configure my root domain name to display the app directory once I enter the command grunt, but the only way it currently works is at website.com:8080/!#/. How can I get it to ...