Node.js 애플리케이션에서 순환 종속성 문제를 해결한 방법

16639 단어 javascript
나는 당신이 겪었을 수도 있는 문제와 당신의 node.js 경력의 어떤 지점을 소개할 것입니다.
일반적으로 나는 내 비즈니스 로직을 내 코드의 다른 모든 것과 분리하고(이름을 서비스로 지정하겠습니다) 일부 작업을 수행하는 데 필요한 리소스를 트리거하는 비즈니스 계층이었습니다. 경우에 따라 이 비즈니스 계층의 한 항목이 동일한 계층의 다른 항목을 사용해야 합니다.

예시:

로그인 자격 증명을 생성하려면 CustomerService에 UserService가 필요합니다.

다른 순간에 UserService는 CustomerService를 호출하여 고객 프로필을 확인합니다.

실패 시나리오:





|--/services/CustomerService.js

const UserService = require('./UserService')

class CustomerService{
    create() {
        UserService.create();
        console.log('Create Customer');
    }

    get() {
       return {
          name: 'test'
       }
    }
}

module.exports = new CustomerService;



|--/서비스/UserService.js

const CustomerService = require('./CustomerService')
class UserService {
    create() {
        console.log('Create user');
    }

    get() {
        let customer = CustomerService.get();
        console.log({customer});
    }
}
module.exports = new UserService;


|--/index.js

const CustomerService = require('./services/CustomerService');
const UserService = require('./services/UserService');

CustomerService.create();
UserService.get();


따라서 이 코드를 구현하고 터미널에서 node index.js를 실행하면 다음 오류가 발생합니다.



당신은 생각할 수 있습니다 : WTF ??? 하지만 이 방법이 존재합니다!!!!

네, 제 반응이었습니다. 두 모듈 사이에 종속성을 생성할 때 발생하는 순환 종속성으로 인해 이 오류가 발생합니다. 이는 CustomerService 내에서 UserService를 가져와 사용하고 그 반대의 경우도 마찬가지임을 의미합니다.

이 문제를 어떻게 해결할 수 있습니까? 한 가지 가능한 해결책.



index.js라는 중앙 집중식 파일에 모듈을 로드할 것이므로 이후에는 index.js 파일만 가져오고 사용해야 하는 개체를 지정합니다.



실습:



1 - services 폴더 안에 index.js 파일을 만듭니다(주의: 중요한 코드 스니펫입니다).

|--/services/index.js

const fs = require('fs');
const path = require('path');
const basename = path.basename(__filename);
const services = {};

// here we're going to read all files inside _services_ folder. 
fs
    .readdirSync(__dirname)
    .filter(file => {
        return (file.indexOf('.') !== 0) &&
                (file !== basename) &&
                (file.slice(-3) === '.js') &&
                (file.slice(-8) !== '.test.js') &&
                (file !== 'Service.js')
    }).map(file => {
        // we're are going to iterate over the files name array that we got, import them and build an object with it
        const service = require(path.join(__dirname,file));
        services[service.constructor.name] = service;
    })

    // this functionality inject all modules inside each service, this way, if you want to call some other service, you just call it through the _this.service.ServiceClassName_.
    Object.keys(services).forEach(serviceName => {
        if(services[serviceName].associate) {
            services[serviceName].associate(services);
        }
    })

module.exports = services;


2 - 생성하는 각 서비스에서 상속할 상위 클래스를 생성해 봅시다.

|--/서비스/Service.js

class Service {
    associate(services) {
        this.services = services;
    }
}

module.exports = Service;


3 - 어떻게 될지 확인하기 위해 코드를 다시 작성해 봅시다.

|--/services/CustomerService.js

const Service = require('./Service')
class CustomerService extends Service{
    create() {
        this.services.UserService.create();
        console.log('Create Customer');
    }
    get() {
       return {
          name: 'test'
       }
    }
}

module.exports = new CustomerService;


|--/서비스/UserService.js

// now you only import the Service.js
const Service = require('./Service.js')
class UserService extends Service{
    create() {
        console.log('Create user');
    }

    get() {
        // now we call the service the we want this way
        let customer = this.services.CustomerService.get();
        console.log({customer});
    }
}
module.exports = new UserService;


4 - 이제 서비스 폴더 외부에서 서비스를 호출하는 방법을 살펴보겠습니다.

// now we only import the index.js (when you don't set the name of the file that you're intending to import, automatically it imports index.js)
const {CustomerService, UserService} = require('./services/')
// and we call this normally
CustomerService.create();
UserService.get();



장점:
  • 이제 순환 종속성 오류 없이 다른 서비스를 더 쉽게 로드할 수 있습니다.
  • 다른 서비스 내에서 서비스를 사용해야 하는 경우 this.service.NameOfTheService 속성을 호출하기만 하면 됩니다.

  • 단점:
  • 가져오기 핸들러가 코드 내부에 있고 더 이상 사용하려는 모듈에 직접 있지 않기 때문에 IDE 또는 코드 편집기에서 더 이상 추적할 수 없습니다.
  • 일부 모듈은 사용되지 않지만 모든 모듈의 로드로 인해 약간의 성능 손실이 있습니다.



  • 혼란스럽거나 이해에 영향을 미치거나 개선할 수 있다고 생각하는 경우 귀하의 피드백에 감사하겠습니다.

    너희들을보고 많이 감사합니다

    좋은 웹페이지 즐겨찾기