是否有任何原因为什么在调用navigator.mediaDevices.getUserMedia时没有发现错误?

时间:2019-01-16 02:23:01

标签: webrtc es6-promise getusermedia

我正在通过使用最新的Chrome Windows版本同时访问2个摄像头来编写Webrtc chrome桌面应用程序。

可以通过navigator.mediaDevices.enumerateDevices()访问摄像机列表,但是无法使用navigator.mediaDevices.getUserMedia通过其特定ID访问这些设备。

它仅在某些时候发生。但在捕获中没有错误。

因此,我尝试了navigator.mediaDevices.getUserMedia是否确实存在。

if(navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia){ }

是的。

只是在调用navigator.mediaDevices.getUserMedia()时未获取任何日志信息

getVideoSources_ = function() {
    return new Promise(function(resolve, reject) {
        if (typeof navigator.mediaDevices.enumerateDevices === 'undefined') {
            alert('Your browser does not support navigator.mediaDevices.enumerateDevices, aborting.');
            reject(Error("Your browser does not support navigator.mediaDevices.enumerateDevices, aborting."));
            return;
        }

        requestVideoSetTimeout = 500;
        navigator.mediaDevices.enumerateDevices().then((devices) => {

            // get the list first by sorting mibunsho camera in first place
            for (var i = 0; i < devices.length; i++) {
                log("devices[i]", JSON.stringify(devices[i]));
                log("devices[i].label", devices[i].label);
                if (devices[i].kind === 'videoinput' && devices[i].deviceId && devices[i].label) {
                    if (devices[i].label.indexOf("USB_Camera") > -1) {
                        deviceList[1] = devices[i];
                    } else {
                        deviceList[0] = devices[i];
                    }
                }
            }

            // request video by sorted plan
            for (var i = 0; i < deviceList.length; i++) {
                requestVideo_(deviceList[i].deviceId, deviceList[i].label, resolve, reject);
                requestVideoSetTimeout = 1000; // change requestVideoSetTimeout for next video request
            }
        }).catch((err) => {
            log("getVideoSources_:" + err.name + ": " + err.message);
            reject(Error("getVideoSources_ catch error"));
        });
    });
}
getVideoSources_().then(function(result) {
    ....
}).catch(function(err) {
    ....
});

function requestVideo_(id, label, resolve, reject) {
    if (navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        log("navigator.mediaDevices.getUserMedia found!");

        navigator.mediaDevices.getUserMedia({
            video: {
                deviceId: {exact: id},
                width: 640,
                height: 480,
                frameRate: {
                    ideal: 20,
                    max: 20
                }
            },
            audio: false}).then(
            (stream) => {
                log("***requestVideo_", id);
                log("***requestVideo_", label);
                log("***requestVideo_", stream);
          // USB_Camera is face camera
          if (label.indexOf("USB_Camera") > -1) {
            log("***requestVideo_001");
            myStream2 = stream;
            log("***requestVideo_myStream2", myStream2);
          } else {
            log("***requestVideo_002");
            myStream = stream;
            log("***requestVideo_myStream", myStream);
            getUserMediaOkCallback_(myStream, label);
          }
          resolve("###Video Stream got###");

          stream.getVideoTracks()[0].addEventListener('ended', function(){
            log("***Camera ended event fired. " + id + " " + label);
            endedDevice[id] = label;
          });
      },
      getUserMediaFailedCallback_
      ).catch((error) => {
        log('requestVideo_: ' + error.name);
        reject(Error("requestVideo_ catch error" + error.name));
      });
    }
}

function getUserMediaFailedCallback_(error) {
    log("getUserMediaFailedCallback_ error:", error.name);
    alert('User media request denied with error: ' + error.name);
}

1 个答案:

答案 0 :(得分:2)

@Kaiido是正确的,resolve在此处的for循环中被调用,该循环遍地都是,并且在所有代码完成之前。此点之后的任何错误基本上都会丢失。

这是promise constructor anti-pattern。简而言之:不要在promise构造函数中编写应用程序代码。不要向下传递resolvereject函数。相反,让函数将承诺返回给您,并在所有then回调中添加所有应用程序代码。然后返回所有诺言,使它们形成一条链。只有这样,错误才能正确传播。

有关更多信息,请参见Using promises on MDN