1

So it's been hours and hours i'm breaking my head to get this async schema working:

1) I have a function prepare message which is async as it needs to get download an attachment

2) I have a function send message which calls gmail api and sends the prepared message This function returns a callback function which i'm willing to use onSuccess

3) I have a loop for which calls this sendMessage function, which calls the preparemessage function

Everything works as expected, the loop creates N calls with N answers However the callback function is apparently configured before and gets the result of the last value in the for.

This is part of the code:

arrayOfMessagesToBeSent=[{msg1},{msg2}...] (got from the store)

for (const x of arrayOfMessagesToBeSent) {

store.actions.gapi.sendMessage(
        await store.actions.mailing.prepareMsg(
          {messageStuf}     

        ),
        (answer) => {
        console.log("call:", x.id);
        store.actions.mailing.sendCallback(answer, x.id);
      };
      );

}

Once prepare message is finished, the message is sent. I get one valid answer per email sent However the loop for keeps running in the background and overrides that x.id value

store.actions.mailing.sendCallback(answer, x.id); => Answer follows the good flux => Answer is different for each message => x.id gets overrided and all the times this function is executed, gets only the x.id

Do you know how could I synchronize it? So basically i want the callbackfunction (or that x.id variable) to wait until prepare message is finished.

Option A: The best one: Messages get ready while others are being sent. This would be the best solution

Option B: If it is impossible, at least the flux:

1)prepare 2)send 3)callback and then go with second message 1)prepare 2)send 3)callback... would be good enough

Note: I don't want to use promise-all with a .map(). I dont want to prepare ALL messages and then send ALL messages, a loop for and option B would be a better implementation for my use case.

Thank you!

Loïc V
  • 517
  • 7
  • 9
  • 2
    Can you show your actual code, please? `x` is not defined in your code. Probably it is declared outside the loop which leads to the [standard closure in loop problem](https://stackoverflow.com/q/750486/1048572), but we can only guess. – Bergi Apr 30 '20 at 12:01
  • I am wondering if "store.actions.gapi.sendMessage" is asynch as well. Not that it is or isn't part of the problem - but there needs to be more to go on. – akaphenom Apr 30 '20 at 12:03
  • 1
    Actually it sounds like you *do* want to use `Promise.all` and `map`, which allows preparing all messages at once and sending each message as soon as it is prepared (while others are still getting prepared), and waiting for everything to be done in the end. Or do the messages really need to be prepared sequentially? In any case, you will want to promisify `sendMessage` so that you don't have to pass a callback. – Bergi Apr 30 '20 at 12:03

1 Answers1

0

So I guess I could get option A using promise.all. I thought the functions would execute once all promisses are solved...

But meanwhile I solved it already (option B) thanks to @Bergi. Just promissifing that ugly callback and now I can just do it step by step like this:

  const MSG = await store.actions.mailing.prepareMsg(
    {msg stuff}
  );
  const answer = await store.actions.gapi.sendMessagePromise(MSG);
  const doStuff = store.actions.mailing.sendCallback(answer, x.id);

No message is being prepared until the first one is already sent but it is alright :)

Loïc V
  • 517
  • 7
  • 9