Проблема с зависимостью модуля NestJs

Я работаю над приложением NestJs, в котором я создал вспомогательный класс и использую функцию из класса модуля внутри этого вспомогательного класса. но я получаю некоторые ошибки. Сначала я получал неопределенную ошибку, затем я сделал вспомогательный класс инъекционным, а затем снова столкнулся с проблемами зависимостей.

Это ошибка, с которой я сталкиваюсь в настоящее время.

Error: Nest can't resolve dependencies of the BoomiService (?). Please make sure that the argument dependency at index [0] is available in the CronjobsModule context.

Potential solutions:
- If dependency is a provider, is it part of the current CronjobsModule?
- If dependency is exported from a separate @Module, is that module imported within 
CronjobsModule?
@Module({
 imports: [ /* the Module containing dependency */ ]
})

at Injector.resolveSingleParam (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\injector.js:178:19)
at resolveParam (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\injector.js:116:49)
at Array.map (<anonymous>)
at Injector.resolveConstructorParams (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\injector.js:131:58)
at Injector.loadInstance (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\injector.js:57:24)
at Injector.loadProvider (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\injector.js:84:20)
at D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\instance-loader.js:47:62
at Array.map (<anonymous>)
at InstanceLoader.createInstancesOfProviders (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\instance-loader.js:47:36)
at D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\instance-loader.js:32:24
at Array.map (<anonymous>)
at InstanceLoader.createInstances (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\instance-loader.js:31:49)
at InstanceLoader.createInstancesOfDependencies (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\injector\instance-loader.js:21:20)
at D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\nest-factory.js:96:38
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Function.asyncRun (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\errors\exceptions-zone.js:22:13)
at NestFactoryStatic.initialize (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\nest-factory.js:94:13)
at NestFactoryStatic.create (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\node_modules\@nestjs\core\nest-factory.js:37:9)
at bootstrap (D:\WorkData\AGData\JavascriptProjects\orion\orion-gateway-api\src\main.ts:9:15)

Это мой вспомогательный класс.

                import axios from "axios";
            import * as qs from'querystring';
            import { OpenApiService } from "../open-api/open-api.service";
            import {
                BadRequestException,
                Injectable,
                NotFoundException,
              } from '@nestjs/common';
            @Injectable()
            export class BoomiService {
                constructor(private OpenApiService: OpenApiService) {}
                //get services
                // 
                //Post services
                createRenewalRequest = async (data) => {
                    const config = {
                        headers: {
                            'Content-Type': 'application/json',
                            "x-api-key": process.env.BOOMI_APIKEY
                        }
                    };
                    // console.info('data',data)
                    try {
                        // console.info('here in createQRFeedbackForComm',config);
                        return axios.post(
                            `${process.env.BOOMI_API_BASEURL}${process.env.BOOMI_POST_APIENDPOINT}`,
                            JSON.stringify(data),
                            config
                        ).then(async (response) => {
                            const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:response.data,reqData:data,type:'CXMRenewalRequest',status:'Completed'});
                            return response.data;
                            }).catch(async (e) => {
                                const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:e,reqData:data,type:'CXMRenewalRequest',status:'Failed'});
                            return (`error in createRenewalRequest => ${e}`);
                        });
                        
                    } catch (e) {
                        const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:e,reqData:data,type:'CXMRenewalRequest',status:'Completed'});
                        throw e;
                    }
                }
                createMaintainenceRequest = async (data) => {
                    const config = {
                        headers: {
                            'Content-Type': 'application/json',
                            "x-api-key": process.env.BOOMI_APIKEY
                        }
                    };
                    try {
                        console.info('response->',this.OpenApiService)
                        // console.info('here in createQRFeedbackForComm',config);
                        return axios.post(
                            `${process.env.BOOMI_API_BASEURL}${process.env.BOOMI_POST_APIENDPOINT}`,
                            JSON.stringify(data),
                            config
                        ).then(async (response) => {
                            const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:response.data,reqData:data,type:'CXMMaintainenceRequest',status:'Completed'});
                            return response.data;
                        }).catch(async (e) => {
                            console.info('response=',e)
                            const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:e,reqData:data,type:'CXMMaintainenceRequest',status:'Failed'});
                            return (`error in createMaintainenceRequest => ${e}`);
                        });
                    } catch (e) {
                        const boomilogs = await this.OpenApiService.saveOpenApiLogs({reason:e,reqData:data,type:'CXMMaintainenceRequest',status:'Failed'});
                        throw e;
                    }
                }
            }

здесь я использую метод saveOpenApiLogs из OpenApiService.

Это мой файл службы Open API.

                import {
              BadRequestException,
              Injectable,
              NotFoundException,
            } from '@nestjs/common';
            import { HttpService } from '@nestjs/axios';
            import * as moment from 'moment';
            import constants from '../config/constant';
            import { CreateOpenApiDto } from './dto/create-open-api.dto';
            import { UpdateOpenApiDto } from './dto/update-open-api.dto';
            import { empty, firstValueFrom } from 'rxjs';
            import { error } from 'console';
            import { PropertyDto } from './dto/property.dto';
            import utils from 'src/utils/utils';
            import { util } from 'prettier';
            import { CCAService } from 'src/utils/ccaService';
            import {BoomiService} from 'src/utils/BoomiService';
            import { v4 as uuidv4 } from "uuid";
            var {
              communityList,
              nationalityList,
              leaseNatureList,
              leaseTypeList,
              paymentScheduleArrName,
              paymentStatusForAGP,
              bhoomi_x_api_key,
            } = constants;
            const numberWithDastPattern = /^(\-?\d+)$/;
            const mobileNumberPattern = /^(\+?\d+)$/;

            @Injectable()
            export class OpenApiService {
              constructor(
                private ccaService: CCAService,
                private BoomiService: BoomiService,
                private httpService: HttpService,
              ) {}
              propertyAPI = process.env.PROPERTY_API;
              userAPI = process.env.USER_API;
              maintenanceAPI = process.env.MAINTENANCE_API;
              leaseAPI = process.env.LEASING_API;
              
              async sendMaintainenceNotificationToBoomi() {
                
                  let DataResponse = {},boomiResponse = {}
                  try {
                    const url = `${this.maintenanceAPI}ticket`;
                    let params: any = {};
                    params.todayTickets=  true;
                    params.perPage=  100;
                    params.ticketStatus=  'issue_resolved,ag_not_responsible,landlord_not_responsible,reject';
                      let ticketData:any = await this.httpService
                      .get(
                        url, {params},
                      )
                      .toPromise()
                      .catch((e) => {
                        console.info('Error in todayTickets',e);
                        throw new Error(e.response.data.error);
                      });
                      // console.info('ticketData',ticketData.data.result.data);
                    if (ticketData && ticketData.data.result.data && ticketData.data.success) {
                      let tickets = ticketData.data.result.data;
                      let dataForBoomi:any[] =  []
                      console.info('tickets -> length',tickets.length)
                      if (tickets.length>0){
                        await Promise.all(tickets.map(async (ticket) =>{
                          // console.info('ticket',ticket);
                          const url = `${this.userAPI}user/detail`;
                          const unit_url = `${this.propertyAPI}unit?unitId=${ticket?.unitId}&status=enable&select=propertyName,unit.unitNumber,address.community,address.subCommunity`;
                            let Tenant: any = await firstValueFrom(
                              this.httpService.post(url, {user:ticket?.tenantId}),
                            ).catch((e) => {
                              console.info('ERROR---', e);
                              throw new Error(e.response.data.error);
                            });
                            // console.info('Tenant',Tenant?.data?.result)
                            let unit:any = await this.httpService
                            .get(
                              unit_url,
                            )
                            .toPromise()
                            .catch((e) => {
                              console.info('Error in get unit',e);
                              throw new Error(e.response.data.error);
                            });
                            // console.info('unit',unit?.data?.result.data[0])
                          dataForBoomi.push(
                            {
                              "firstName": Tenant?.data?.result?.name||"",
                              "lastName":  Tenant?.data?.result?.name||"",
                              "fullName":  Tenant?.data?.result?.name||"",
                              "emailId": Tenant?.data?.result?.email||"",
                              "whatsAppPhoneNumber": Tenant?.data?.result?.mobile||"",
                              "propertyType": "Residential",
                              "unitLeased": unit?.data?.result?.data[0]?.unit?.unitNumber||"",
                              "propertyName": unit?.data?.result?.data[0]?.propertyName||"",
                              "location": unit?.data?.result?.data[0]?.address?.community||"",
                              "subLocation": unit?.data?.result?.data[0]?.address?.subCommunity||"",
                              "communicationType": "Email",
                              "complaintType":"MAINTENANCE_REQUEST",
                              "complaintSubType": ticket?.ratingAndReview?.rating||'',
                              "businessUnit": "Properties",
                              "eventType": "MAINTENANCE_REQUEST",
                              "transactionDate": ticket?.updatedAt,
                              "categoryOfMaintenance": ticket?.category?.name||'',
                              "technicianAssigned": ticket?.technician?.name||'',
                              "attachmentURL": "",
                              "userType": "",
                              "comments": ticket?.ratingAndReview?.comment||''
                            }
                          );
                          // console.info('dataForBoomi',dataForBoomi)
                          return dataForBoomi
                        })).then(async (dataForBoomi) => {
                          // console.info('dataForBoomi',dataForBoomi)
                            let PayloadForBoomi = {
                              "QRCodeFeedback": dataForBoomi[0]
                            }
                            // console.info('PayloadForBoomi',PayloadForBoomi)
                            boomiResponse = await this.BoomiService.createMaintainenceRequest(PayloadForBoomi)
                            // console.info('boomiResponse:',boomiResponse)
                          console.info('------boomiResponse-----', boomiResponse);
                          DataResponse = boomiResponse;
                            return DataResponse
                          })
                          .catch(error => {
                            console.error('Error:', error);
                          });
                      }          
                    }
                  } catch (error) {
                    DataResponse = error;
                  }
                  return {
                    DataResponse
                  };
                }

                async saveOpenApiLogs(reqBody=null){
                  console.info('reqBody',reqBody)
                  return await firstValueFrom(
                    this.httpService.post(`${this.userAPI}openAPItenantStatus`, {
                      uuid: uuidv4(),
                      reason: reqBody?.reason||'',
                      request: reqBody?.reqData?JSON.stringify(reqBody.reqData):'',
                      type: reqBody?.type||'',
                      status: reqBody?.status||'pending',
                    }),
                  ).catch((e) => {return e});
                }
            }

Я удалил ненужные методы из этого класса, иначе код был бы беспорядочным.

это мой файл открытого модуля API, в который я импортировал вспомогательный класс.

        import { Module } from '@nestjs/common';
        import { OpenApiService } from './open-api.service';
        import { OpenApiController } from './open-api.controller';
        import { HttpModule } from '@nestjs/axios';
        import { CCAService } from 'src/utils/ccaService';
        import { BoomiService } from 'src/utils/BoomiService';
        import { BookingModule } from 'src/booking/booking.module';
        import { CronjobsModule } from 'src/cronjobs/cronjobs.module';

        @Module({
          controllers: [OpenApiController],
          providers: [OpenApiService,CCAService,BoomiService],
          imports: [HttpModule,BookingModule,CronjobsModule],
        })
        export class OpenApiModule {}

Это файл модуля, для которого я получаю сообщение об ошибке

        import { Module } from '@nestjs/common';
    import { CronjobsService } from './cronjobs.service';
    import { HttpModule } from '@nestjs/axios';
    import { NotificationModule } from 'src/notification/notification.module';
    import { MaintenanceService } from 'src/maintenance/maintenance.service';
    import { OpenApiService } from 'src/open-api/open-api.service';
    import { CCAService } from 'src/utils/ccaService';
    import { BoomiService } from 'src/utils/BoomiService';
    import { BookingModule } from 'src/booking/booking.module';

    @Module({
      imports:[HttpModule, NotificationModule,BookingModule],
      providers: [CronjobsService, MaintenanceService,OpenApiService,CCAService,BoomiService]
    })
    export class CronjobsModule {}

Я новичок в NestJs и не могу разобраться в проблеме. кто-нибудь еще сталкивался с тем же? Пожалуйста, подскажите решение.

Спасибо

похоже, у вас какая-то циклическая зависимость. Прочтите страницу часто задаваемых вопросов на сайте документацииnesjs.

Micael Levi 15.04.2024 17:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
1
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это потому, что у вас есть циклическая зависимость. Это означает, что модуль импортируется\вводится в цикле.

В твоем случае:

  • в OpenApiService вы импортируете «BoomiService».
  • также в BoomiService вы импортируете OpenApiService.

Всякий раз, когда инициализируется среда выполнения OpenApiService, она вызывает Boomi, затем Boomi вызывает openAi и так далее.

Циклическая зависимость обычно является ошибкой архитектурного решения с вашей стороны.

Я заметил, что в вашем openAiService вы используете только один метод из BoomiService.

boomiResponse = await this.BoomiService.createMaintainenceRequest(PayloadForBoomi)

Было бы проще извлечь это и переместить куда-нибудь еще. Но также комментарий к этой строке и удаление импорта бумисервиса в вашем openaiService должны устранить ошибку и запустить ваш гнездовой проект. Это просто для подтверждения концепции.

Что следует сделать, так это, возможно, создать третий сервис, который импортирует как Boomi, так и OpenAi, и там создать функцию, которая вызывает то, что вы хотите, и когда выдаются ошибки, регистрируйте их.

Это также сделает ваш код чище и упростит его выполнение вместо связывания асинхронных функций и использования результатов в .then().

Это также обсуждается в документации NestJs.

Вы правы, я исправил это, удалив циклическую зависимость. В моем BoomiService я удалил импорт OpenApiService и переместил его код оттуда в сам OpenApiService. это решило мою проблему. Спасибо за Ваш ответ

Owais Aslam 16.04.2024 11:32

Другие вопросы по теме