Andrew Kruglik
Andrew Kruglik

Reputation: 302

Code inside async function ignores await property

my problem is in order of execution: the connectToNewUser function, which is called inside wait() function, get executed before the myPeer.on('call'), which is also inside it. I put my code into async\await function, but no result, somehow "user-connected" executes first. If I add timeout to connectToNewUser

socket.on('user-connected', userId => {
    setTimeout(connectToNewUser,1000,userId,stream)
  })

, it start to work as I need, but I want to solve it using await. Where is a problem?

 const socket = io("/");
const videoGrid = document.getElementById("video-grid");
const myPeer = new Peer(undefined, {
    host: "/",
    port: "3001"
});

const myVideo = document.createElement('video');
myVideo.muted = true;
const peers = {};

navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
}).then(stream => {
    addVideoStream(myVideo, stream);

    wait(myPeer, stream);
});

socket.on("user-disconnected", userId => {
    peers[userId] && peers[userId].close();
});

myPeer.on("open", id => {
    socket.emit("join-room", ROOM_ID, id);
})

const connectToNewUser = (userId, stream) => {
    const call = myPeer.call(userId, stream);
    const video = document.createElement('video');
    
    call.on("stream", userVideoStream => {
        addVideoStream(video, userVideoStream);
    });

    call.on("close", () => {
        video.remove();
    });

    peers[userId] = call
}

const addVideoStream = (video, stream) => {
    video.srcObject = stream;
    video.addEventListener('loadedmetadata', () => {
        video.play();
    })

    videoGrid.append(video);
} 

async function wait(myPeer, stream) {
    await myPeer.on("call", call => {
        call.answer(stream);

        const video = document.createElement("video");

        call.on("stream", userVideoStream => {
            addVideoStream(video, userVideoStream)
        })
    });

    await socket.on("user-connected", userId => {
        connectToNewUser(userId, stream);
    });
}

Upvotes: 1

Views: 425

Answers (2)

Quentin
Quentin

Reputation: 943999

await is a tool for managing promises.

await myPeer.on("call", doesn't return a promise so you can't usefully await it.

await myPeer.on("call", does take a callback so you might be able to wrap it in a promise. However…

Promises are a standard API for handing things that happen asynchronously once.

myPeer.on("call", looks like it happens every time you get a call, which would make it unsuitable for use with promises. If so you should continue to use the callback API it provides (through you might want to look at RxJs which tries to do for repeated events what Promises do for non-repeated events).

Not everything asynchronous is suitable for use with await.

Upvotes: 2

Chris Kao
Chris Kao

Reputation: 503

Try this:

function waitCall(myPeer) {
  return new Promise((resolve) => {
    myPeer.on("call", call => {
      resolve(call)
    })
  })
}

function waitStream(myPeer){
  return new Promise((resolve) => {
    myPeer.on("stream", userVideoStream => {
      resolve(userVideoStream)
    })
  })
}

function waitUserConnected(myPeer){
  return new Promise((resolve) => {
    myPeer.on("user-connected", userId => {
      resolve(userId)
    })
  })
}

async function wait(myPeer, stream){
  const call = await waitCall(myPeer)
  call.answer(stream)
  
  const video = document.createElement("video")
  const userVideoStream = await waitStream(myPeer)
  addVideoStream(video, userVideoStream)

  const userId = await waitUserConnected(myPeer)
  connectToNewUser(userId, stream)
}

Upvotes: 0

Related Questions