-1

I am trying out JS and wrapping my head around its async model. There is a project I am building for practice. It is a simple audio calling app using webRTC.

A scenario I am having trouble understanding is given below:


User A can mute their mic via calling mute_mic(). This function is as follows:

async function mute_mic(e) {

    let credential_payload = await retrieveOwnCred();// sensitive data, get from server, don't trust client

    // do other mic muting stuff

}

User B is the host of the call. So they can remove User A's mic. To do that, the host sends a signal to User B. User B's client then executes the following:

async function leave_mic() {

    stopped = await stopPublishingStream(streamID);  
    // some other clean up

}

At times this happens: User A is muting their mic, while the host has simultaneously asked to take their mic away. I can see unpredictable stuff happening. Maybe it is because the execution of the two async functions gets mixed up?

If that is the case, what is the best pattern to handle a situation like this? Can an industry expert provide an illustrative example?

I would want these functions to run synchronously, one after another. But I also need them to be async, since there is an await call within them. What tactics can I employ here?

Liam
  • 27,717
  • 28
  • 128
  • 190
Hassan Baig
  • 15,055
  • 27
  • 102
  • 205
  • Are you sure you have host/UserA/userB correct in your description? "user B is host, can mute user A, so the host sends a signal to B" doesn't sound right - if B is the host, then they already have the signal. – freedomn-m Aug 24 '20 at 11:02
  • *"Maybe it is because the execution of the two async functions gets mixed up?"* - Are you asking us that or telling us that? The code shown has no obvious problems, and the only description of the issue so far is "unpredictable stuff [is] happening", so we can't really say what specifically is failing. But we can assure you that when you `await` an `async` operation, the following code is not executed until that operation completes. (Until the `Promise` resolves.) Can you be more specific about the problem or provide a more concrete example demonstrating it? – David Aug 24 '20 at 11:03
  • `await mute_mic; await leave_mic` will essentially run in a synchronous order. – Liam Aug 24 '20 at 11:05
  • you are mixing local actions (mute mic, triggered from a button click) with remote actions (moderator takes mic away). This is somewhat similar to https://jsfiddle.net/fippo/vd2gq3sn/2/ -- the second click event doesn't wait for the first one to be finished – Philipp Hancke Aug 24 '20 at 13:17
  • @PhilippHancke yes I realize that is the case – Hassan Baig Aug 24 '20 at 13:21
  • 1
    Sounds like a non-problem since nothing "unpredictable" happens if two near-random event handlers try to mute at the same time. Microphone mute is idempotent. A more interesting case might be the host muting and the user unmuting at nearly the same time, but that's an app logic question. – jib Aug 24 '20 at 13:29

1 Answers1

2

the nub of your question, to me, seems to be:

Maybe it is because the execution of the two async functions gets mixed up?

This shouldn't be happening. You can easily chain these two functions by simply doing:

await mute_mic(); 
await leave_mic();

In the above leave_mic() will always run after mute_mic().

the only reason I can see that these wouldn't run in the correct order would be if you did something like:

mute_mic(); 
leave_mic();

These functions are still asynchronous, the await just retains the ordering. This is because async/await is simply syntactical sugar for a promise, so you could also think of/write the above as:

mute_mic()
.then(() => {
   leave_mic();
});

See Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference for more information on this.


how do I call it when attaching it to the onclick state of a button

I'd just declare a new function:

function async click_handler() {
   await mute_mic(); 
   await leave_mic();
}

mute_mic_btn.onclick = click_handler;

Again, remember this is still async you can't return something from this directly. The async/await is just flattering the structure for you. If your new to JS get to grips with promises.

Liam
  • 27,717
  • 28
  • 128
  • 190
  • Fair enough, but how do I call it when attaching it to the onclick state of a button, i.e. `mute_mic_btn.onclick = mute_mic;`. I cannot include `await` there right. – Hassan Baig Aug 24 '20 at 11:14
  • Moreover, for completeness,could you add a small explanation in lay terms about how calling `await func` is fundamentally different from `func` - given `func` is `async` in both cases. – Hassan Baig Aug 24 '20 at 13:16
  • `func` **is not async**, `async func` is async. @HassanBaig Functions are not async by nature, they become async when you add the async keyword. Like I've already explained, `async` is just a code short cut for promises. I'd suggest you [read and understand these](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) and the other links I've already added in this answer – Liam Aug 24 '20 at 13:52
  • [Specifically this question](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Liam Aug 24 '20 at 13:56