1

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);
    });
}
Andrew Kruglik
  • 182
  • 1
  • 11

2 Answers2

2

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.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Looks like you are right) I can fix it using RxJs Scheduler, but it much more comlicated, than simple timeout function. Thanks for your reply! – Andrew Kruglik May 26 '21 at 08:56
0

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)
}
Chris Kao
  • 410
  • 4
  • 12