Employing aspect.around while actively monitoring for methods invoking one another

Seeking a solution to run specific code around the put() and add() functions for Dojo stores, I encountered an issue with JSON REST stores where add() simply calls put():

add: function(object, options){
  options = options || {};
  options.overwrite = false;
  return this.put(object, options);
},

Using aspect.around() with add() causes my code to run twice if applied to stores created with a store that treats add() as a shortcut to put().

I understand that this is a common practice among most stores, but I want my solution to work seamlessly with any store, regardless of method nesting.

Dojo's Observable.js faces a similar challenge and handles it in the following manner:

function whenFinished(method, action){
    var original = store[method];
    if(original){
      store[method] = function(value){
        if(inMethod){
          return original.apply(this, arguments);
        }
        inMethod = true;
        try{
          var results = original.apply(this, arguments);
          Deferred.when(results, function(results){
            action((typeof results == "object" && results) || value);
          });
          return results;
        }finally{
          inMethod = false;
        }
      };
    }
  }
  
  whenFinished("put", function(object){
    store.notify(object, store.getIdentity(object));
  });

  whenFinished("add", function(object){
    store.notify(object);
  });

  whenFinished("remove", function(id){
    store.notify(undefined, id);
  });

The question remains: Is there a concise way to modify my current code to check if it's already within a method, thus preventing duplicate execution?

I attempted to streamline my code but ended up with a clumsy, makeshift solution. It seems like I'm overlooking something simpler...

This is my current code snippet:

topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){

  aspect.around( store, 'put', function( put ){

    return function( object, options ){

      return when( put.call( store, object, options ) ).then( function( r ) {
        var eventName;
        var identity = store.idProperty;
        eventName = object[ identity ] ? 'storeRecordUpdate' : 'storeRecordCreate';

        topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[ identity ], object: object }, false );

      } );

    }
  });

  aspect.around( store, 'add', function( add ){
    return function( object, options ){

      return when( add.call( store, object, options ) ).then( function( r ) {

        var identity = store.idProperty;

        topic.publish('storeRecordCreate', null, { storeName: storeName, storeTarget: storeTarget, objectId: r[identity], object: object }, false }  );

      });
    }
  });
});

Answer №1

Here's my take on it... One thing that's bothering me about my approach is whether it's completely foolproof.

Let's say store.add() gets called twice in a row. Is there a scenario where the first call sets inMethod to true, and then the second call finds it set to true because the first one didn't have time to set it back to false yet?

This might only be possible if nextTick() is invoked between the two calls, right?

Or perhaps I'm just overcomplicating things? (That wouldn't be surprising...)

  topic.subscribe( 'hotplate/hotDojoStores/newStore', function( storeName, store ){

    var inMethod;

    aspect.around( store, 'put', function( put ){

      return function( object, options ){

        if( inMethod ){
          return when( put.call( store, object, options ) );
        } else {

          inMethod = true;

          try {
            return when( put.call( store, object, options ) ).then( function( r ) {
              var eventName;
              var identity = store.idProperty;
              eventName = object[identity] ? 'storeRecordUpdate' : 'storeRecordCreate';

              topic.publish( eventName, null, { type: eventName, storeName: storeName, objectId: r[identity], object: object }, false );

            });
          } finally {
            inMethod = false;
          }

        }

      }
    });

    aspect.around( store, 'add', function( add ){
      return function( object, options ){

        if( inMethod ){
          return when( add.call( store, object, options ) );
        } else {

          inMethod = true;

          try {

            return when( add.call( store, object, options ) ).then( function( r ) {

              var identity = store.idProperty;

              topic.publish('storeRecordCreate', null, { type: 'storeRecordCreate', storeName: storeName, objectId: r[identity], object: object }, false );

            });
          } finally {
            inMethod = false;
          }
        }
      }

    });

    aspect.around( store, 'remove', function( remove ){
      return function( objectId, options ){

        return when( remove.call( store, objectId, options ) ).then( function( r ) {

          topic.publish('storeRecordRemove', null, { type: 'storeRecordRemove', storeName: storeName, objectId: objectId }, false );

        });
      };
    });

  });

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

When a table row is selected, set the OnClick attribute of an input to the value of the TD cell in that row based on

I'm really struggling with this. So, here's the issue - I have a table where rows get assigned a class (selected) when clicked on. Now, there's an input inside a form that needs to redirect to another page when clicked, and it also needs t ...

Mocha retries causing logging malfunction: a problem to address

My current situation involves testing something on our network, and occasionally the network experiences delays causing the test to end prematurely. To address this issue, I attempted to set the test to retry with the command this.retries(1). While this ...

Is there a way to update a JSON key using the "onchange" function in React?

I'm facing an issue. I have a form with two inputs. The first input is for the key and the second input is for the value. I need to update the values in the states whenever there is a change in the input fields, but I'm unsure of how to accomplis ...

As the background image shifts, it gradually grows in size

I'm attempting to create an interesting visual effect where a background image moves horizontally and loops seamlessly, creating the illusion of an infinite loop of images. Using only HTML and CSS, I've run into an issue where the background ima ...

Puppeteer: Navigate to a specific page number

I'm encountering an issue with a table and page numbers as links, such as: 1, 2, 3, 4 etc… -> each number is a link. Attempted to create a loop to click on different page numbers. On the first iteration, I can reach page 2. However, on the secon ...

Display or conceal a vue-strap spinner within a parent or child component

To ensure the spinner appears before a component mounts and hides after an AJAX request is complete, I am utilizing the yuche/vue-strap spinner. This spinner is positioned in the parent days.vue template immediately preceding the cycles.vue template. The ...

Ways to adjust the width of the Dialog box in Jquery UI to 60% of the window size

Currently, I am utilizing Jquery UI for a pop-up feature that displays a table populated through an Ajax call. The script implementation is as follows: <script> $(function() { $( "#dialog" ).dialog({ autoOpen: false, show: { ...

Tips for broadcasting the blob

I am currently working on a radio system project that involves streaming live audio from a microphone to the user in real-time. However, I am new to using node.js and unsure of how to achieve this. Can anyone provide guidance on how to stream the audio fro ...

reloading a URL dynamically using an array in JavaScript

I need assistance with a Chrome extension code. The goal is to have it check the page that initially loads, and if it matches my website st.mywebsite.com, execute the specified code. Currently, it does not perform this check and runs on every loaded page ...

The scroll feature in JavaScript is malfunctioning

After countless hours of troubleshooting, I still can't figure out why the code snippet below is not working properly on my website at : <script> $(window).scroll(function () { if ($(window).scrollTop() > 400) { ...

Utilizing Node.js callback for validating JWT tokens

In my Node.js server, I have set up an authentication route to authenticate requests: app.get('/loggedin', auth, function(req, res){ console.log(req.authenticated); res.send(req.authenticated ? req.authenticated: false) }) From what I u ...

Expressing the relationship between API endpoints in a nested structure

I'm currently working on a REST API using expressjs. There are two api endpoints that I have defined: router.get('/probe/:id', function() {}); router.get('/:id', function() {}); However, I am facing an issue where calling the fir ...

The class name is not defined for a certain child element in the icon creation function

Currently, I am developing a Vue2 web application using Leaflet and marker-cluster. I am encountering an issue with the iconCreateFunction option in my template: <v-marker-cluster :options="{ iconCreateFunction: iconCreateClsPrg}"> ...

Methods for applying responsive design to react modals in React.js

I am looking to make my modal responsive across different media types. In my React JS project, I have implemented custom styles using the following code: import Modal from 'react-modal'; const customStyles = { content : { top ...

Is there a way to add a fade-in and slide-in effect to this dropdown JavaScript, as well as a fade-out and

Although I lack the necessary knowledge of Javascript, I am aware that my request may be a bit much. The code I currently have is directly from the w3school dropdown-list demo. Would it be possible for you to help me implement a fade in and slide in effect ...

Having trouble publishing project on Vercel because of a naming issue

Whenever I try to deploy a project on vercel, I encounter an error stating that the project name is not valid. The specific error messages are as follows: Error: The name of a Project can only contain up to 100 alphanumeric lowercase characters and hyphe ...

Creating a form submission event through Asp.net code behind

Is there a way to change the onsubmit parameter of a form in an asp.net project, specifically from the master page code behind of a child page? I am interested in updating the form value so that it looks like this: <form id="form1" runat="server" onsu ...

Error: JSON array contains unterminated string literal

Hey there, var favorites = 'Array ( [0] => [" 6 "," 1 "," 2 "," 5 "," 3 "," 4 "] [1] => [" 6 "," 1 "," 2 "," 5 "," 3 "," 4 "] [2] => [" 6 "," 1 "," 2 "," 5 "," 3 "," 4 "] ) '; I've been encountering a syntax error - an untermi ...

The useEffect hook in React is signaling a missing dependency issue

Any tips on how to resolve warnings such as this one src\components\pages\badge\BadgeScreen.tsx Line 87:6: React Hook useEffect has a missing dependency: 'loadData'. Either include it or remove the dependency array react-hoo ...

What is the equivalent of Node's Crypto.createHmac('sha256', buffer) in a web browser environment?

Seeking to achieve "feature parity" between Node's Crypto.createHmac( 'sha256', buffer) and CryptoJS.HmacSHA256(..., secret), how can this be accomplished? I have a piece of 3rd party code that functions as seen in the method node1. My goal ...