1

I'm trying to use database transaction to create a Page record however I'm getting Variable 'createdPage' is used before being assigned even though this.pagesService.create() only returns Page and it will throw error if something goes wrong so program can be sure that createdPage is set if no exception is thrown. So why I'm getting this error?

  @Post('')
  async create(
    @Body() body: PageCreateDto,
  ): Promise<Page> {
    let createdPage: Page;
    try {
      await this.database.transaction(async trx => {
        createdPage = await this.pagesService.create(body, trx);
      });
    } catch (error) {
      throw new InternalServerErrorException('unable to create page');
    }

    return createdPage;
    
  }
Terry
  • 63,248
  • 15
  • 96
  • 118
omidh
  • 2,526
  • 2
  • 20
  • 37
  • Does `this.database.transaction` return a promise? If it doesn't, then the `await` is not doing much there. Usually, if a function accepts a callback to run after it finishes, it doesn't also return a promise. So, my guess would be that the callback won't execute before the `return`. – VLAZ May 14 '21 at 19:59
  • You’re returning the variable immediately: the assignment only occurs asynchronously. In other words, you are not waiting for the async request to populate the variable before returning it. Read up about async/await and how to return responses asynchronously. – Terry May 14 '21 at 19:59
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Terry May 14 '21 at 20:00
  • @VLAZ Yes it returns promise, It is Knex transaction. – omidh May 14 '21 at 20:00
  • @Terry I don't know how but it solved the issue, Can u explain it? – omidh May 14 '21 at 20:08

2 Answers2

1

The problem is that the function you pass into the transaction call doesn't get run synchronously and so you can't be sure that createdPage is actually assigned when you return it. You could solve this by creating a promise.

@Post('')
async create(@Body() body: PageCreateDto): Promise<Page> {
  return new Promise<Page>((resolve, reject) => {
    try {
      await this.database.transaction(trx => this.pagesService
        .create(body, trx)
        .then(resolve));
    } catch (error) {
      reject(new InternalServerErrorException('unable to create page'));
    }
  }); 
}
MrCodingB
  • 2,284
  • 1
  • 9
  • 22
0

Returning it inside arrow function solved the issue:

  @Post('')
  async create(
    @Body() body: PageCreateDto,
  ): Promise<Page> {
    let createdPage: Page;
    try {
      createdPage = await this.database.transaction(async trx => {
        return this.pagesService.create(body, trx);
      });
    } catch (error) {
      throw new InternalServerErrorException('unable to create page');
    }

    return createdPage;
    
  }
omidh
  • 2,526
  • 2
  • 20
  • 37