2016-04-06 4 views
1

У меня вопрос о последовательности JavaScript. Позвольте мне показать вам мой код первым:Назначить значение MediaDevices.enumerateDevices() в глобальной переменной в JavaScript

Вот мой HTML:

<video id="video" width="320" height="320" autoplay></video><br> 
<button id="snap">Snap Photo</button><br> 
<canvas id="canvas" width="320" height="320"></canvas> 
<p id="pngHolder"></p> 

А вот мой JavaScript:

<script> 
var Id; 
//List cameras and microphones. 
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) { 
    console.log("enumerateDevices() not supported."); 
} 
navigator.mediaDevices.enumerateDevices() 
.then(function (devices) { 
    devices.forEach(function (device) { 
     if (device.kind == "videoinput" && device.label.indexOf('back') >= 0) { 
      Id = device.deviceId; 
      alert("ID 1 : " + Id); 
     } 
    }); 
}) 
.catch(function (err) { 
    console.log(err.name + ": " + err.message); 
}); 

// Put event listeners into place 
window.addEventListener("DOMContentLoaded", function() { 
    // Grab elements, create settings, etc. 
    alert("ID 2 : "+ Id); 
    var canvas = document.getElementById("canvas"), 
     videoObj = { 
      video: { 
       optional: [{ deviceId: Id }] 
      } 
     }, 
     context = canvas.getContext("2d"), 
     video = document.getElementById("video"), 
     errBack = function (error) { 
      console.log("Video capture error: ", error.code); 
     }; 

    // Trigger photo take 
    document.getElementById("snap").addEventListener("click", function() { 
     context.drawImage(video, 0, 0, 640, 480); 
     // Get the image 
     var image = convertCanvasToImage(canvas); 
     // Actions 
     document.getElementById("pngHolder").appendChild(image); 
     // Converts canvas to an image 
     function convertCanvasToImage(canvas) { 
      var image = new Image(); 
      image.src = canvas.toDataURL("image/png"); 
      return image; 
     } 
    }); 

    //alert("ID 2 : " + Id); 
    // Put video listeners into place 
    if (navigator.getUserMedia) { // Standard 
     navigator.getUserMedia(videoObj, function (stream) { 
      video.src = stream; 
      video.play(); 
     }, errBack); 
    } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed 
     navigator.webkitGetUserMedia(videoObj, function (stream) { 
      video.src = window.webkitURL.createObjectURL(stream); 
      video.play(); 
     }, errBack); 
    } else if (navigator.mozGetUserMedia) { // Firefox-prefixed 
     navigator.mozGetUserMedia(videoObj, function (stream) { 
      video.src = window.URL.createObjectURL(stream); 
      video.play(); 
     }, errBack); 
    } 
}, false); 

Я хочу, чтобы вставить значение device.deviceId в переменную Id что Я определяю первую строку моего JavaScript. Это все еще успех (это показано alert("ID 1 : " + Id);). Но когда я пытаюсь поместить его в optional: [{ deviceId: Id }], Id не имеет значения.

А также, когда я пытаюсь запустить его в браузере, я обнаружил, что сначала отображается alert("ID 2 : " + Id); вместо alert("ID 1 : " + Id);. На самом деле, я уже положил alert("ID 1 : " + Id);. Я думаю, поэтому переменная все еще пуста.

Вопрос: как я могу вставить значение device.deviceId в optional: [{ deviceId: Id }]?

ответ

1

navigator.mediaDevices.enumerateDevices() является асинхронным. Он возвращает обещание (думаю, обратный вызов, но причудливый).

Вы должны активировать свой вызов в getUserMedia или дождаться как DOMContentLoaded, так и enumerateDevices, а затем выполнить getUserMedia.

5

navigator.mediaDevices.enumerateDevices и DOMContentLoaded участвуют в гонке, и последний выигрывает, поэтому вы используете Id, прежде чем он будет установлен.

Для решения этого используйте временный haveId обещание:

var haveId = navigator.mediaDevices.enumerateDevices() 
    .then(devices => devices.find(d => d.kind == "videoinput" && 
           d.label.indexOf("back") >= 0)); 

// Put event listeners into place 
window.addEventListener("DOMContentLoaded", function() { 
    haveId.then(id => { 
    // Grab elements, create settings, etc. 
    alert("ID 2 : "+ id); 
    var canvas = document.getElementById("canvas"), 
    videoObj = { video: { deviceId: id } }, // <-- adapter.js constraints 

Promise-цепочки создания зависимостей, и этот способ, getUserMedia код обыкновение продолжаться до тех пор, как вещи не произошло.

Вторая проблема заключается в том, что вы смешиваете новые и outdated Chrome-specific constraints. Либо используйте adapter.js, пока Chrome не настигнет, или в крайнем случае, только Chrome-sourceId (но это не будет работать в любом другом браузере).

+0

Извините, я до сих пор не понимаю вашего примера. Я попытался реализовать его, но он показывает ошибки в «=>» и «hasId.then (id => {». Хотели бы вы подробнее рассказать об этом? –

+0

@YusrilMaulidanRaji oh, это [функции стрелок] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), просто используется для краткости здесь. Замените все 'x => y'' функцией (x) {return y;} ' и он должен работать одинаково. – jib

Смежные вопросы