Не удалось выполнить setLocalDescription для RTCPeerConnection - PullRequest
0 голосов
/ 18 ноября 2018

У меня некоторое время возникала эта ошибкакак мой код работает сейчас, он не сможет интегрировать его, и я также слышал, что socket.on уже выполняет асинхронную работу.

Я также пытался использовать точки останова в vs-коде для отладки кода, который не работает должным образом.

Буду очень признателен, если кто-нибудь знает обходной путь для этого.Код прикреплен ниже

'use strict';

var localStream;
var remoteStream;
var isInitiator;
var configuration = {
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302'
    }
  ]
};
var pc = new RTCPeerConnection(configuration);

// Define action buttons.
const callButton = document.getElementById('callButton');
const hangupButton = document.getElementById('hangupButton');

/////////////////////////////////////////////

window.room = prompt('Enter room name:');

var socket = io.connect();

if (room !== '') {
  console.log('Message from client: Asking to join room ' + room);
  socket.emit('create or join', room);
}

socket.on('created', function(room) {
  console.log('Created room ' + room);
  isInitiator = true;
  startVideo();
});

socket.on('joined', function(room) {
  console.log('joined: ' + room);
  startVideo();
});

socket.on('log', function(array) {
  console.log.apply(console, array);
});

////////////////////////////////////////////////

function sendMessage(message) {
  socket.emit('message', message);
}

// This client receives a message
socket.on('message', function(message) {
  try {
    if (message.type === 'offer') {
      pc.setRemoteDescription(new RTCSessionDescription(message));
      // const stream = navigator.mediaDevices.getUserMedia({
      //   audio: true,
      //   video: true
      // });
      // stream.getTracks().forEach(track => pc.addTrack(track, localStream));
      pc.setLocalDescription(
        pc.createAnswer(setLocalAndSendMessage, function(err) {
          console
            .log(err.name + ': ' + err.message)
            .then(pc.setLocalDescription);
        })
      );
    } else if (message.type === 'answer') {
      console.log('This is to check if answer was returned');
      pc.setRemoteDescription(new RTCSessionDescription(message));
    } else if (message.type === 'candidate') {
      pc.addIceCandidate(candidate);
    }
  } catch (err) {
    console.error(err);
  }
});

////////////////////////////////////////////////////

const localVideo = document.querySelector('#localVideo');
const remoteVideo = document.querySelector('#remoteVideo');

// Set up initial action buttons status: disable call and hangup.
callButton.disabled = true;
hangupButton.disabled = true;

// Add click event handlers for buttons.
callButton.addEventListener('click', callStart);
hangupButton.addEventListener('click', hangupCall);

function startVideo() {
  navigator.mediaDevices
    .getUserMedia({
      audio: true,
      video: true
    })
    .then(function(mediaStream) {
      localStream = mediaStream;
      localVideo.srcObject = mediaStream;
    })
    .catch(function(err) {
      console.log('getUserMedia() error: ' + err.name);
    });
  callButton.disabled = false;
}

function callStart() {
  createPeerConnection();
  //pc.addTrack(mediaStream);
  //stream.getTracks().forEach(track => pc.addTrack(track, localStream));
  callButton.disabled = true;
  hangupButton.disabled = false;
  if (isInitiator) {
    console.log('Sending offer to peer');
    pc.createOffer(setLocalAndSendMessage, function(err) {
      console.log(err.name + ': ' + err.message).then(pc.setLocalDescription);
    });
  }
}

/////////////////////////////////////////////////////////

function createPeerConnection() {
  try {
    pc = new RTCPeerConnection(null);
    pc.onicecandidate = ({ candidate }) => sendMessage({ candidate });
    pc.ontrack = event => {
      if (remoteVideo.srcObject) return;
      remoteVideo.srcObject = event.streams[0];
    };
    console.log('Created RTCPeerConnnection');
  } catch (e) {
    console.log('Failed to create PeerConnection, exception: ' + e.message);
    alert('Cannot create RTCPeerConnection object.');
    return;
  }
}

function setLocalAndSendMessage(sessionDescription) {
  console.log('setLocalAndSendMessage sending message', sessionDescription);
  pc.setLocalDescription(sessionDescription);
  sendMessage(sessionDescription);
}

function hangupCall() {
  pc.close();
  pc = null;
}

1 Ответ

0 голосов
/ 19 ноября 2018

Нет обходного пути для понимания асинхронного кода.Вы пресекаете свой путь здесь.

Если вы не собираетесь использовать async / await , то вам нужно бороться с тем, что JavaScript является однопоточным, иникогда не может блокировать ожидание завершения асинхронной операции, поэтому вы никогда не можете просто напрямую использовать возвращаемое значение из асинхронного метода, как вы пытаетесь сделать здесь:

createAnswer - асинхронныйметод, возвращающий обещание , а не ответ, так что это неправильно :

  pc.setLocalDescription(                                    // <-- wrong
    pc.createAnswer(setLocalAndSendMessage, function(err) {  //
      console
        .log(err.name + ': ' + err.message)
        .then(pc.setLocalDescription);
    })
  );

Вы звоните setLocalDescription(promise), что дает вам ошибку, которую выупомянуть, поскольку обещание не является действительным описаниемВместо этого обещание - это объект, к которому вы добавляете обратные вызовы :

const promise = pc.createAnswer();
promise.then(setLocalAndSendMessage, function(err) {
  console.log(err.name + ': ' + err.message);
});

или просто:

pc.createAnswer()
  .then(setLocalAndSendMessage, function(err) {
    console.log(err.name + ': ' + err.message);
  });

Мы можем даже последовательно использовать then для формирования цепочка обещаний :

pc.createAnswer()
  .then(function(answer) {
    return pc.setLocalDescription(answer);
  })
  .then(function() {
    sendMessage(pc.localDescription);
  })
  .catch(function(err) {
    console.log(err.name + ': ' + err.message);
  });

Кроме того, я не должен был вам говорить console.log() не возвращает обещание!

К сожалению, вы копируете действительно старый код здесь, а RTCPeerConnection имеет некоторые устаревшие API и выполняет некоторые трюки, чтобы иногда позволить вызывающим абонентам сойти с рук при вызове этих методов согласования без по-настоящему цепочки обещаний или проверки на наличие ошибок.Но это неизбежно приводит к неприятностям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...