1

As you can see in the .gif below, the first time I call my database it returns data successfully. But the next two times it neither returns nor errors, the asynchronous code simply disappears. And even worse, my await statement doesn't wait for the response, it just continues.

Can anyone tell me why the subsequent calls to Sequelize disappear? And more importantly, why the calling code keeps running even though I've used await?

enter image description here

Here is the innermost code:

getRolesAndPermissionsForUser(userId: string): Promise<[IRoleModel]> {
    return new Promise<[IRoleModel]>( async (resolve: any, reject: any) => {
      try {
        const rows = await this._db.getSequelize().transaction( (transaction) => {
          return this._db.getSequelize().query(getRolesAndPermissionsForUserSql, { type: Sequelize.QueryTypes.SELECT, replacements: [userId]  });
        })
        resolve(this.convertRolesToTree(rows));
      }
      catch (error) { reject(error); }
    });
  }

called by:

async function hasPermission(hapiResolve: (response: any) => void, requestingUserId: string, requestedUserId: string, requestedUsersRoles: any[]): Promise<boolean> {
      return new Promise<boolean>( (resolve, reject) => {
        try {
          //user is seeng her own roles
          let result = (requestingUserId === requestedUserId);

          //user manages a franchisor the requestee is part of
          if (!result) {
            requestedUsersRoles.forEach( async (role) => {
              if (!result) { //may have found it last iteration
                const userHasOrgPermission = await self._bouncer.doesUserHavePermission(null, requestingUserId, DatabaseIds.enum__permissions__canViewAllRolesOfAnyUseratThisFranchisor, role.franchisorId, null)
                if (userHasOrgPermission) result = true;
              }
            })
          }

          //user manages a franchisee the requestee is part of
          if (!result) {
            requestedUsersRoles.forEach( async (role) => {
              if (!result) { //may have found it last iteration
                const userHasOrgPermission = await self._bouncer.doesUserHavePermission(null, requestingUserId, DatabaseIds.enum__permissions__canViewAllRolesOfAnyUseratThisFranchisor, null, role.franchiseeId)
                if (userHasOrgPermission) result = true;
              }
            })
          }

          if (!result)
            hapiResolve(responseHelper.getErrorResponse(ResponseErrorCode.notAuthorised));
          resolve(result);
        }
        catch (error) {
          console.trace(error);
          reject(error);
        }
      });
    }

  doesUserHavePermission(hapiResolve: (response: any) => void, userId: string, permissionId: string, franchisorId: string, franchiseeId: string): Promise<boolean> {
    return new Promise<boolean>( async (resolve, reject) => {
      try {
        const roles = await this._rolesQueries.getRolesAndPermissionsForUser(userId);
                if (!this.doRolesHavePermission(roles, permissionId, franchisorId, franchiseeId)) {
          if (hapiResolve)
            hapiResolve(responseHelper.getErrorResponse(ResponseErrorCode.notAuthorised));
          resolve(false);
        }
        else resolve(true);
            }
      catch (error) {
        if (hapiResolve)
                hapiResolve(responseHelper.getErrorResponse(ResponseErrorCode.unknownError));
                reject(error);
            }
        });
  }
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Richard
  • 14,798
  • 21
  • 70
  • 103
  • 1
    Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi Jun 22 '16 at 08:50
  • `forEach` does not wait for anything. And it returns nothing you can await. Don't use it. – Bergi Jun 22 '16 at 08:53
  • 1
    Thanks @Bergi. forEach is synchronous according to this: http://stackoverflow.com/questions/5050265/javascript-node-js-is-array-foreach-asynchronous And I don't see how the promise anti-pattern you referenced applies to my code, especially now that `await` is available to us in Javascript. Could you please post an answer with some code? – Richard Jun 22 '16 at 08:59
  • 2
    Yes, `forEach` is synchronous. Which means it doesn't care about the promises returned by the functions you use for its callbacks. – Bergi Jun 22 '16 at 09:01
  • 1
    Oh, I see your duplicated question now. I'll change to a `for` loop and see if that makes a difference. – Richard Jun 22 '16 at 09:01
  • 1
    `async function`s are functions that already return promises. As such, you should not wrap them in a `new Promise` call. Put the `async` keyword on the method, omit the `return new Promise( (resolve, reject) => {` line, replace `resolve` by `return` and `reject` by `throw`, and you will have exactly the same behaviour but less fluff, overhead and antipatterns. – Bergi Jun 22 '16 at 09:04
  • Excellent, the `for` loop works. But I don't understand why - that question I linked to said `forEach` is synchronous, i.e. it blocks, it waits, unlike `map` which is asynchronous and won't wait for the `await` statements. Maybe that linked answer is just wrong. – Richard Jun 22 '16 at 09:16
  • 3
    No, `map` and `forEach` are no different in that regard. There are no blocking asynchronous functions in JS. Your callbacks are *synchronously returning promises* to the loop (which will be ignored by `forEach` and put in an array by `map`) and your code runs concurrently without being awaited by anything. – Bergi Jun 22 '16 at 09:18

0 Answers0