Tips for preventing circular dependencies in JavaScript/TypeScript

How can one effectively avoid circular dependencies? This issue has been encountered in JavaScript, but it can also arise in other programming languages.

For instance, there is a module called translationService.ts where upon changing the locale, settings need to be reloaded (resulting in the need to import settingsService.ts). However, within the settingsService.ts, there is a function reloadSettings that relies on the translationService for translating error messages.

The ideal scenario would be for the translationService to have no knowledge of the settingsService. But how can this separation be achieved through code?

translationService.ts

import { reloadSettings } from '@/services/settingsService.ts'

// When the locale is changed, we want to reload the settings
const changeLocale = (locale: string) => {
  i18n.locale = locale

  reloadSettings()
}

However, in settingsService.ts, there exists a dependency on the translationService for displaying exceptions in the correct locale.

settingsService.ts

import settingsApi from '@/api/settingsApi.ts'
import { translate } from '@/services/translationService.ts'

const reloadSettings = () => {
  try {
    settingsStore.settings = settingsApi.getSettings()
  } catch (error) {
    console.log(
      translate(error.message)
    )
  }
}

This results in a loop of dependencies where settingsService requires translationService and vice versa:

settingsService -> translationService -> settingsService

Answer №1

In many instances similar to this one, it is advisable to reduce two-way coupling by eliminating at least one dependency and replacing it with an indirect form of coupling

Consider the following scenario.

For example, in my settingsService.ts file, there is a reloadSettings function that relies on the translationService to translate error messages.

It seems appropriate to maintain this direct dependency on your translation service since it operates at a lower level.

Within my translationService.ts module, I aim to reload settings whenever the locale changes, which requires importing settingsService.ts.

However, there is no necessity for a direct dependency in this case.

An alternative approach could involve implementing an event emitter that triggers a locale-changed event, allowing the settings service to simply subscribe to this event.

This way, there is no direct dependency; both services rely on the event emitter for communication while remaining decoupled from each other.

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

The seamless merging of Angular2, TypeScript, npm, and gulp for enhanced development efficiency

I'm fairly new to front-end development and I am currently working on an application using Angularjs2 with TypeScript in Visual Studio 2015. I have been following the steps outlined in this Quickstart https://angular.io/docs/ts/latest/cookbook/visual- ...

HTML animation effect on subpage with a URL modification [LATEST UPDATE]

Can you smoothly load a new subpage in the background, update the URL, and fade it in while an animation is playing on the previous page? Check out this example (jsFiddle) to see a simple animation: $(document).ready(function() { 'use strict&apo ...

Obtaining the translated text from the script in Vue JS using Vue Translate

My code currently looks something like this: <template> <div> {{ text }} </div> </template> <script> export default { data: () => ({ text: 'Hello world' }) } </script> I am tryin ...

Best practices for handling HTTP requests in Angular 5

I'm currently developing multiple applications using Angular 5. My aim is to adhere to all the dos and don'ts of Angular. However, I'm facing some confusion regarding a few things. 1) What is the difference between this... this._http.g ...

Embedding a YouTube video in a view player using HTML5

So I've got a question: can you actually open a youtube video using an HTML5 video player? I'm looking for a more mobile-friendly way to watch youtube videos, and my idea was to upload a thumbnail image and then set up an onclick function to disp ...

Transform HTML into a Vue component dynamically during runtime

Currently, I am in the process of learning Vue and working on a simple wiki page project. The raw article data is stored in a JSON file written using custom markup. For example, the following markup: The ''sun'' is {r=black black} shoul ...

What is the best way to locate elements with the term "download" in them using Selenium's x-path feature?

I'm currently utilizing Selenium for web scraping purposes and I am in need of a way to identify all clickable elements that contain the word "download" (regardless of capitalization) within their link text, button text, element ID, element class, or ...

jQuery must provide the complete object rather than just the data within it

What is the best way to retrieve the entire <div class="loan_officer_apply_now_link"><a href="">APPLY NOW!</a></div> At present, only the "a" element content is being returned <a href="">APPLY NOW!</a> Test Code $( ...

Angular SPA boasting an impressive one million pages

Currently, I am in the process of transitioning my webshop, which contains numerous products, to an Angular SPA application using ngRoute and HTML5 mode. I have come up with a method where I receive some of my routes from the server as a JSON object, but s ...

The Angular MatStepper is unable to detect saved values from two string arrays, although it is able to detect values from a different string array

In my application, there is a MatStepper component that facilitates navigation through the signup flow. A method exists to load cached values when available, causing the MatStepper to skip to Page 2. Subsequently, another method pre-fills the form with the ...

Vue components fail to display properly when transitioning between routes in Vue (version 3) using the Vue Router

Just diving into VueJS version 3 and vue-router. Despite my efforts to troubleshoot by consulting Stack Overflow and Google, the issue remains unresolved. I have defined two routes: /login /admin/index The Problem: While the login route ...

Refining a selection from a list using a multi-choice array

I have a filtering component that filters a list of people based on multiple input values. The string-based inputs filter properly, but when I select more than one item in the multi-select, nothing is displayed. This is likely due to person.role not contai ...

There has been an issue with parsing the JSON file due to an invalid character found at

I keep encountering a parse error whenever I attempt to send a post request to the server. $.post("../php/user_handler.php", formData, function(data) { var result = JSON.parse(data); if(result.status === 'error') { ...

Achieving CommonJS imports compilation with Typescript

In my TS file, I've included a 3rd party package using import XXX { YYY, ABC, 123 } from 'XXX'; While it compiles to CommonJS without any issues, I'd prefer to have it compiled to an ESModule instead. I tried changing the target and mo ...

Having trouble with Vue Router view not functioning properly in my Laravel Blade page

While diving into the world of Vue.js, I encountered a perplexing issue. After successfully running ExampleComponent.vue in my admin panel and displaying its content, I attempted to import routes from an external file (new_route_list.js) and load them via ...

The sequence of HTML attributes

Could there be a subjective angle to this question (or maybe not)... I work on crafting web designs and applications using Visual Studio and typically Bootstrap. When I drag and drop a CSS file into an HTML document, the code generated by Visual Studio loo ...

Is there a way to show text as symbols in Primeng components?

Check out this helpful example that demonstrates what I am attempting to achieve. I have implemented p-menu from primeng. Is there a method to convert text into symbols like &trade to ™ and &#8482 to ®? ...

What is the best way to retrieve the value of the nearest text input using JavaScript?

I am currently working on designing an HTML table that includes a time picker in one column for the start time and another time picker in a separate column for the end time within the same row. My goal is to retrieve both values (start time and end time), ...

Unlocking Extended Functionality in JQuery Plugins

At the moment, I am utilizing a JQuery Plugin known as Raty, among others. This particular plugin typically operates as follows: (function($){ $.fn.raty = function(settings, url){ // Default operations // Functions ...

Retrieve information from an ajax response in XML format

AJAX Call Code Example $.ajax({ url: '/services/LTLGadgetV2.aspx', type: 'Get', success: function (result) { console.log( result); } }); The response in the console: Sample XML <RateResults xmlns ...