Асинхронная функция, работающая в Express, но не NestJS

#javascript #node.js #typescript #express #nestjs

#javascript #node.js #typescript #экспресс #nestjs

Вопрос:

Изначально я создал небольшой сервер Express для запуска отчета и функции записи в файл.

 var ssrs = require('mssql-ssrs');
var fs = require('fs');

const express = require('express')
const app = express()
const port = 3001

app.get('/', (req, res) => {
    reportCreation();
    res.send('File Created');
})

app.get('/api', (req, res) => {
    reportCreation();
    res.json({'File Created': true});
})

app.listen(port, () => {
    console.log(`Report Api listening at http://localhost:${port}`)
})
  

Функция reportCreation() — это асинхронная функция, которая получает отчет из SSRS. Это работает нормально

 async function reportCreation() {
var serverUrl = 'http://reportServerName/ReportServer/ReportExecution2005.asmx';

ssrs.setServerUrl(serverUrl);

var reportPath = '/ApplicationPortalReports/TestReportNew';
var fileType = 'word';
var parameters = { ApplicationId: 3, TrainingCardId: 267, PortalPersonId: 52 }

var auth = {
    username: 'USERNAME',
    password: 'PASSWORD',
    domain: 'dmz'
};

try {
    var report = await ssrs.reportExecution.getReportByUrl(reportPath, fileType, parameters, auth)
} catch (error) {
    console.log(error);
}
console.log(report);
try {
    fs.writeFile('ReportApiTest.doc', report, (err) => {
        if (!err) console.log('Data written');
    });
} catch (error) {
    console.log(error);

}
  

В последнее время я много работал с NestJS и хотел использовать ту же функцию, но в службе NestJS.

 @Injectable()
export class AppService {

  async  getReport(): Promise<string> {
   
    const serverUrl = 'http://reportServerName/ReportServer/ReportExecution2005.asmx';

    ssrs.setServerUrl(serverUrl);
    const reportPath = '/ApplicationPortalReports/TestReportNew';
    const fileType = 'word';
    // var parameters = {appId: 3, ReportInstanceId: 1 }
    const parameters = {ApplicationId: 3, TrainingCardId: 267, PortalPersonId: 52 };

    const auth = {
      username: 'USERNAME',
      password: 'PASSWORD',
      domain: 'dmz'
    };

    try {
       var report = await ssrs.reportExecution.getReportByUrl(reportPath, fileType, parameters, auth)
      } catch (error) {
        console.log(error);
      }
      console.log(report);

      // excel = xlsx
      // word = doc
      // pdf = pdf
    try {
      fs.writeFile('ReportApiTest.doc', report,  (err) => {
          if (!err) { console.log('Data written'); 
        return 'File Written Succesfully'}
        });
      } catch (error) {
          console.log(error);
          return 'File Write Error'
      }
      }
  }
  

Как вы можете видеть, файлы почти идентичны, но когда я запускаю его через NestJS, я получаю ошибку, которая выглядит как проблема со строкой

 var report = await ssrs.reportExecution.getReportByUrl(reportPath, fileType, parameters, auth)
  

не ожидает. Почему это работает с Express, а не с NestJS? Ниже приведена ошибка от NestJS

 buffer.js:219
  throw new ERR_INVALID_ARG_TYPE(
  ^

TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer,
Array, or Array-like Object. Received type undefined
    at Function.from (buffer.js:219:9)
    at new Buffer (buffer.js:179:17)
    at Object.createType3Message (C:ProjectsSSRS-report-apissrs-report-apinode_moduleshttpntlmntlm.js:172:19)
    at sendType3Message (C:ProjectsSSRS-report-apissrs-report-apinode_moduleshttpntlmhttpntlm.js:77:23)
    at Immediate._onImmediate (C:ProjectsSSRS-report-apissrs-report-apinode_moduleshttpntlmhttpntlm.js:101:4)
  

в пакете узла mssql-ssrs getReportByURL выглядит следующим образом

 async function getReportByUrl(reportPath, fileType, params, auth) {
    try {
        var config = {
            binary: true, // very important
            username: auth.userName,
            password: auth.password,
            workstation: auth.workstation,
            domain: auth.domain,
            url: soap.getServerUrl()
                  "?"   (testReportPath(reportPath).replace(/s/g, ' '))
                  "amp;rs:Command=Renderamp;rs:Format="   reportFormat(fileType)
                  formatParamsToUrl(params)
        };
    } catch (err) { report.errorHandler(err) }

    return new Promise((resolve, reject) => {
        config.url = encodeURI(config.url);
        httpntlm.post(config, function (err, res) {
            if (res.statusCode === 500) { reject(res) }
            if (err || res.statusCode !== 200) { reject(err) }
            else { resolve(res.body) }
        })
    })
  

}

Вот app.controller.ts

 @Controller()
export class AppController {
     constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): Promise<string> {
    return this.appService.getReport();
  }
}
  

Комментарии:

1. Где находится реализация метода getReportByUrl?

2. Почему у вас есть операторы возврата в writeFiles , а не в коде express?

3. В ошибке четко указано Array, or Array-like Object. Received type undefined . Итак, вы должны сначала сравнить значение объекта конфигурации из express и nestjs. Похоже, что в значении есть разница.

4. @Bwizard можете ли вы поддержать комментарий, который вам помог

5. Ваше использование try..catch совершенно неправильно. Если вы хотите зарегистрировать ошибку, это нормально, но тогда вам нужно throw или как минимум return удалить try..catch . В довершение всего, действительно хитрое и коварное использование var — это то, что позволяет вам даже выйти сухим из воды. Позор вам за то, что вы делаете это с собой!

Ответ №1:

Это не ответ на вопрос. Но после того, как я увижу ваш код, я смогу увидеть ошибку, с которой вы столкнетесь в будущем, если await ssrs.reportExecution.getReportByUrl(reportPath, fileType, parameters, auth) произошел сбой. На самом деле вы видите ошибку выше из-за этого.

Способ, которым вы использовали try catch, действительно плох.

Вот как я это кодирую.

 @Injectable()
export class AppService {

  async  getReport(): Promise<string> {
    const serverUrl = 'http://reportServerName/ReportServer/ReportExecution2005.asmx';

    ssrs.setServerUrl(serverUrl);
    const reportPath = '/ApplicationPortalReports/TestReportNew';
    const fileType = 'word';
    // var parameters = {appId: 3, ReportInstanceId: 1 }
    const parameters = {ApplicationId: 3, TrainingCardId: 267, PortalPersonId: 52 };

    const auth = {
      username: 'USERNAME',
      password: 'PASSWORD',
      domain: 'dmz'
    };

    const report = await ssrs.reportExecution.getReportByUrl(reportPath, fileType, parameters, auth)

    return new Promise(function(resolve, reject) {
        fs.writeFile('ReportApiTest.doc', report, , function(err) {
            if (err) reject(err);
            resolve("File Created");
        });
    });
  }
  

И в моем контроллере

 @POST
async writeFile() {
    try {
        const res = await this.appService.getReport();
        return res;
    } catch(err) {
        // handle your error
    }
}
  

Ответ №2:

Я подделал код в node_module, изменив переменную userName на username и не сделал того же самого в версии NestJS. Я забыл, что сделал это, так что теперь это работает.

Комментарии:

1. Просто удалите вопрос. Это не отвечает на заданный вопрос.