0

Trying to build a more complex return of a MySQL query but the return doesn't wait for the forEach loop to complete.

export const Query = (query: string, values?: Array<string | number>) => {
    return new Promise<Array<any>>((resolve, reject) => {
        pool.query(query, values, (err, results) => {
            if(err) reject(err);
            return resolve(results);
        });
    });
};
const getUsersChats = async(userid: number) => {
    let chats = await Query('SELECT * FROM users_chats u JOIN direct_chats d ON d.id = u.chatid WHERE u.userid = ?', [userid]);
    //console.log(chats);
    let buildReturn: any = [];
    const build = async() => {
        chats.forEach(async(chat) => {
            let buildInnerObject = {};
            let lastMsg = await Query('SELECT * FROM messages WHERE chatid = ? ORDER BY created DESC LIMIT 1', [chat.id]);
            buildInnerObject = {...chat, lastMSG: lastMsg}
            buildReturn.push(buildInnerObject);
        });
    }
    await build();
    console.log(buildReturn)
    return buildReturn;
}

I'm looking for a return of something like:

  {
    id: 12,
    userid: 28,
    chatid: 12,
    created: 2021-01-05T23:14:03.000Z,
    userid_1: 28,
    userid_2: 31,
    title: 'Title',
    lastMSG: [ [RowDataPacket] ]
  },
  {
    id: 13,
    userid: 28,
    chatid: 13,
    created: 2021-01-05T23:18:40.000Z,
    userid_1: 28,
    userid_2: 33,
    title: 'Title'
    lastMSG: []
  }
]

but right now my return is []

  • You never call `build`.... so its code isn't executing at all. Also, it seems quite inefficient to do separate queries for each chat.id. Why not do one query where you select them all? – trincot Jan 08 '21 at 09:17
  • my mistake I forgot to post updated const. Even when build is called my return doesn't wait. and yeah I thought about that, but I'm not sure how to write a query that would select the most recent message of a specific chatid. – mitchell gams Jan 08 '21 at 09:23

1 Answers1

0
  1. You are not calling the build function to get the values.
  2. If you do not await the query for messages, you will not be able to returns it from your function.
  3. You should type properly your data so it's easier to use and to spot errors

Look at the following and ask me questions if there is any point of interrogation


playground


function Query<T>(_query: string, _values?: Array<string | number>): Promise<T[]> {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve([{
          id: 'foo',
        }] as unknown as T[]);
      }, 50);
    });
};

interface Chat {
  id: string;
}

interface Messages {
  example: string;
}

type MyExtendedChat = Chat & {
  lastMSG: Messages[];
};

const getUsersChats = async(userid: number): Promise<MyExtendedChat[]> => {
    const chats: Chat[] = await Query<Chat>(
      'SELECT * FROM users_chats ...',
      [
        userid,
      ],
    );

    const buildReturn: MyExtendedChat[] = await Promise.all(chats.map(async(chat) => {
      const lastMsg: Messages[] = await Query<Messages>(
        'SELECT * FROM messages ...',
        [
          chat.id,
        ],
      );

      return {
        ...chat,
        lastMSG: lastMsg,
      };
    }));

    console.log(buildReturn);

    return buildReturn;
}

(async() => {
  await getUsersChats(42);
})();
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69