Вызовы Twilio заблокированы несколькими экземплярами устройств, которые не уважают Twilio.Device.destroy()

Я работаю над приложением Twilio, где у пользователя будет публичный список номеров перед ним. Некоторые SIP, некоторые традиционные. Конечный пользователь может нажать кнопку, чтобы вызвать одного человека из списка, поговорить и уйти - тогда другой пользователь подойдет и позвонит другому человеку.
Я сталкиваюсь с проблемой, когда Twilio.Device.destroy не удаляет все устройства в игре, и второй пользователь в этом примере в конечном итоге вызовет цель первого пользователя.
Сначала код, затем журналы:
кнопка крючка:

$('.twilio-voice').click(function() {
    var toNum = this.value;
    console.log('To num in jq');
    console.log(toNum);
    makeVoiceCall(toNum);
});


Функция makeVoiceCall:

var makeVoiceCall = function(toNum) {
    console.log('To Num Is:');
    console.log(toNum);
    if(localStorage.token == undefined) {
        console.log("In If");
        getVoiceToken(toNum);
    } else {
        console.log("In Else");
        console.log(localStorage.token);
        Twilio.Device.setup(localStorage.token, {debug: true});
        Twilio.Device.ready(function(device){
            console.log('IN READY TO NUM IS');
            console.log(toNum);
            Twilio.Device.connect({"To": toNum});
        });
        Twilio.Device.error(function(error) {
            console.log(error.message);
            if(error.message == 'JWT Token Expired') {
                getVoiceToken(toNum);
            };
        });
    }
};


Есть слушатель событий, который запускает модальный файл Twilio.Device.connect, который создает модальную кнопку, которая при нажатии И слушатель событий отключения, которые оба вызывают функцию зависания:

function hangup() {
    Twilio.Device.disconnectAll();
    Twilio.Device.destroy();
};


Я попытался добавить Twilio.Device.destroy(); в начале makeVoiceCall, внутри Twilio.Device.ready(); и наверху утверждения else, и они, кажется, не имеют никакого эффекта. Вот как будут выглядеть журналы, если я нажму на традиционный номер, а затем на номер глотка. Традиционный номер вызывается дважды. Если номер SIP вызывается первым, то он будет вызван, если после этого будет предпринята попытка использовать традиционный номер. В этом примере уже есть токен в localStorage, когда страница загружена.

To num in jq
ts:1214 +15555555555
ts:1178 To Num Is:
ts:1179 +15555555555
ts:1190 In Else
ts:1191 
[STACKOVERFLOW EDIT: console logged token removed]
twilio.min.js:71 Device.sounds is deprecated and will be removed in the next 
breaking release. Please use the new functionality available on 
Device.audio.
m.defaultWarnHandler @ twilio.min.js:71
m.deprecated @ twilio.min.js:71
(anonymous) @ twilio.min.js:72
l @ twilio.min.js:71
a @ twilio.min.js:39
setup @ twilio.min.js:59
makeVoiceCall @ ts:1192
(anonymous) @ ts:1215
dispatch @ jquery-2.1.3.min.js:3
r.handle @ jquery-2.1.3.min.js:3
twilio.min.js:70 [Device] Setting up PStream
twilio.min.js:70 [WSTransport] Opening socket
twilio.min.js:70 [WSTransport] attempting to connect
twilio.min.js:70 [WSTransport] Socket opened
twilio.min.js:70 [PStream] Setting token and publishing listen
twilio.min.js:70 [Device] Stream is ready
ts:1194 IN READY TO NUM IS
ts:1195 +15555555555
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "have-local-offer"
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "stable"
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "checking"
xb @ jquery-2.1.3.min.js:3
get @ jquery-2.1.3.min.js:3
css @ jquery-2.1.3.min.js:3
get @ jquery-2.1.3.min.js:3
cur @ jquery-2.1.3.min.js:3
init @ jquery-2.1.3.min.js:3
Kb @ jquery-2.1.3.min.js:3
createTween @ jquery-2.1.3.min.js:3
Rb.* @ jquery-2.1.3.min.js:3
Ub @ jquery-2.1.3.min.js:3
Vb @ jquery-2.1.3.min.js:3
Xb @ jquery-2.1.3.min.js:3
g @ jquery-2.1.3.min.js:3
dequeue @ jquery-2.1.3.min.js:3
(anonymous) @ jquery-2.1.3.min.js:3
each @ jquery-2.1.3.min.js:2
each @ jquery-2.1.3.min.js:2
queue @ jquery-2.1.3.min.js:3
animate @ jquery-2.1.3.min.js:3
n.fn.(anonymous function) @ jquery-2.1.3.min.js:3
addModal @ ts:974
(anonymous) @ ts:1024
a.emit @ twilio.min.js:162
(anonymous) @ twilio.min.js:48
c @ twilio.min.js:165
a.emit @ twilio.min.js:163
mediaStream.onopen @ twilio.min.js:21
a.version.pc.onsignalingstatechange @ twilio.min.js:119
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "completed"
twilio.min.js:70 [Connection] Disconnecting...
twilio.min.js:70 [PStream] Closing PStream
twilio.min.js:70 [WSTransport] Closing socket
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "closed"
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "closed"
twilio.min.js:158 WebSocket connection to 'wss://chunderw-vpc-gll.twilio.com/signal' failed: Close received after close
l._connect @ twilio.min.js:158
l.open @ twilio.min.js:157
a @ twilio.min.js:78
a @ twilio.min.js:75
a._setupStream @ twilio.min.js:54
a.register @ twilio.min.js:50
a @ twilio.min.js:46
setup @ twilio.min.js:59
makeVoiceCall @ ts:1192
(anonymous) @ ts:1215
dispatch @ jquery-2.1.3.min.js:3
r.handle @ jquery-2.1.3.min.js:3
twilio.min.js:70 [WSTransport] Socket received error: undefined
twilio.min.js:70 [WSTransport] Socket closed
twilio.min.js:70 [Device] Stream is offline
ts:1213 To num in jq
ts:1214 sip:test@sipexample.info
ts:1178 To Num Is:
ts:1179 sip:test@sipexample.info
ts:1190 In Else
ts:1191 [STACKOVERFLOW EDIT: token console.logged]
twilio.min.js:70 [Device] Found existing Device; using new token but ignoring options
twilio.min.js:70 [Device] Setting up PStream
twilio.min.js:70 [WSTransport] Opening socket
twilio.min.js:70 [WSTransport] attempting to connect
twilio.min.js:70 [WSTransport] Socket opened
twilio.min.js:70 [PStream] Setting token and publishing listen
twilio.min.js:70 [Device] Stream is ready
[STACKOVERFLOW EDIT: HERE IS WHERE TWO DEVICES ARE CALLED BY ONE Twilio.Device.setup()]
ts:1194 IN READY TO NUM IS
ts:1195 +15555555555
ts:1194 IN READY TO NUM IS
ts:1195 sip:test@sipexample.info
twilio.min.js:51 Uncaught Error: A Connection is already active
    at a.connect (twilio.min.js:51)
    at Function.connect (twilio.min.js:60)
    at a.<anonymous> (ts:1196)
    at a.emit (twilio.min.js:163)
    at a.<anonymous> (twilio.min.js:55)
    at a.emit (twilio.min.js:163)
    at l.transport.onmessage (twilio.min.js:78)
    at WebSocket.c.onmessage (twilio.min.js:160)
a.connect @ twilio.min.js:51
connect @ twilio.min.js:60
(anonymous) @ ts:1196
a.emit @ twilio.min.js:163
(anonymous) @ twilio.min.js:55
a.emit @ twilio.min.js:163
transport.onmessage @ twilio.min.js:78
c.onmessage @ twilio.min.js:160
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "have-local-offer"
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "stable"
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "checking"
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "completed"
twilio.min.js:70 [Connection] Disconnecting...
twilio.min.js:70 [PStream] Closing PStream
twilio.min.js:70 [WSTransport] Closing socket
twilio.min.js:70 [Twilio.PeerConnection] iceConnectionState is "closed"
twilio.min.js:70 [Twilio.PeerConnection] signalingState is "closed"
twilio.min.js:158 WebSocket connection to 'wss://chunderw-vpc-gll.twilio.com/signal' failed: Close received after close
l._connect @ twilio.min.js:158
l.open @ twilio.min.js:157
a @ twilio.min.js:78
a @ twilio.min.js:75
a._setupStream @ twilio.min.js:54
a.register @ twilio.min.js:50
setup @ twilio.min.js:59
makeVoiceCall @ ts:1192
(anonymous) @ ts:1215
dispatch @ jquery-2.1.3.min.js:3
r.handle @ jquery-2.1.3.min.js:3
twilio.min.js:70 [WSTransport] Socket received error: undefined
twilio.min.js:70 [WSTransport] Socket closed
twilio.min.js:70 [Device] Stream is offline

Как вы можете видеть в нижней четверти журналов - помечены моим дополнением: [STACKOVERFLOW EDIT: HERE IS WHERE TWO DEVICES ARE CALLED BY ONE Twilio.Device.setup()]и SIP, и традиционный номер вызываются во время отдельного вызова Twilio.Device.setup, даже если устройство было уничтожено с помощью функции зависания (и я пробовал другие точки для размещения Twilio.Device.destroy). Из-за этого только исходный набранный номер подключается со второй попытки.
На данный момент единственные обходные пути, о которых я могу подумать, - это создать индивидуальные функции для каждого человека в списке (что является антитезой для DRY и добавляет массу работы по обслуживанию или расширению этого кода) или перезагрузить страницу. после завершенного звонка (который мой работодатель не любит).
Если бы я мог просто отпустить / уничтожить устройства Twilio после завершения вызовов, это бы мне очень помогло. Я пытался разместить Twilio.Device.disconnect(function() { Twilio.Device.disconnectAll(); Twilio.Device.destroy();}); под моим вызовом Twilio.Device.connect внутри готово, с такими же результатами. Любая помощь по уничтожению этих нескольких устройств (или повторное использование первого) была бы неоценима.

1 ответ

Решение

Twilio разработчик евангелист здесь.

Вам не нужно уничтожать Twilio.Device после каждого звонка. На самом деле здесь происходит то, что вы регистрируете несколько обработчиков, которые вызываются при Device становится ready,

Я бы посоветовал переделать это несколько. Когда страница загрузится, настройте устройство Twilio. Затем прослушайте офлайн-события, чтобы узнать, когда нужно сгенерировать токен и повторно подключиться к службе. Что-то вроде:

function makeVoiceCall(toNum) {
  Twilio.Device.connect({"To": toNum});
}

function setupDevice(token) {
  Twilio.Device.setup(token, { debug: true });
}

function getVoiceToken(callback) {
  $.post('/token', function(data) {
    localStorage.token = data.token;
    callback(token);
  })
}

function init() {
  if(localStorage.token == undefined) {
    getVoiceToken(function(token){ 
      setupDevice(token)
    });
  } else {
    setupDevice(localstorage.token)
  }

  // Ready will setup click handlers.
  Twilio.Device.ready(function() {
    $('.twilio-voice').click(function() {
      var toNum = this.value;
      makeVoiceCall(toNum);
    });
  });

  // offline will remove click handlers, get a new token and setup the device again
  Twilio.Device.offline(function() {
    // unregister click handlers for now
    $('.twilio-voice').off('click');
    getVoiceToken(function(token) {
      setupDevice(token);
    })
  })
}

window.addEventListener('load', init);

Я составил новую версию getVoiceToken вот так, чтобы он возвращал токен в обратном вызове, что, я думаю, облегчает чтение.

Дайте мне знать, если это поможет.

Другие вопросы по тегам