如何修复承诺i̶n̶̶F̶i̶r̶e̶f̶o̶x̶?

时间:2017-06-25 04:56:36

标签: javascript angularjs promise es6-promise

以下是我的Promise代码的简化示例:

var sharedLocalStream = null;
// ...
function getVideoStream() {
  return new Promise(function(resolve, reject) {
    if (sharedLocalStream) {
      console.log('sharedLocalStream is defined');
      resolve(sharedLocalStream);
    } else {
      console.log('sharedLocalStream is null, requesting it');
      navigator
          .mediaDevices
          .getUserMedia(constraints)
          .then(function(stream) {
            console.log('got local videostream', stream);
            sharedLocalStream = stream;
            resolve(sharedLocalStream);
          })
          .catch(reject);
    }
  });
}

我在几个地方异步使用这个功能。 这个问题与函数被调用至少两次这一事实有关,但在第二次调用时,承诺永远不会得到解决/拒绝。 此代码在Chrome中完美运行。我也尝试使用Angular promises service $ q,但它也没有用。

我做错了什么以及如何使这段代码有效?

此外,我正在考虑如何在这种情况下避免承诺,我别无选择,因为当用户确认麦克风和相机访问请求时我被迫等待。

更新

var constraints = {
    audio: true,
    video: true
  };

2 个答案:

答案 0 :(得分:2)

如果getVideoStream()被调用两次,则代码会出现并发问题。因为在第一次调用getVideoStream()之前第二次调用sharedLocalStream已更新sharedLocalStream变量时,没有强制排队或排序,您很容易就会遇到这样的情况:调用是在var sharedLocalStreamPromise = null; function getVideoStream() { // if we've already requested a local stream, // return the promise who's fulfilled value is that stream if (!sharedLocalStreamPromise) { sharedLocalStreamPromise = navigator.mediaDevices.getUserMedia(constraints).catch(function(err) { // clear the promise so we don't cache a rejected promise sharedLocalStreamPromise = null; throw err; }); } return sharedLocalStreamPromise; } 有值之前启动的。

这是代码设计的问题,而不是您运行它的平台。通常的做法是将第一个操作的promise保存到共享变量中。然后,您将测试是否已经存在承诺。如果有,你只需要回报这个承诺。

如果您缓存promise而不是流,则可以像这样简单地执行:

sharedLocalStreamPromise

第一个电话会将java.util.Calendar初始化为承诺。当第二个呼叫(或任何后续呼叫)进入时,它将返回相同的承诺。

我正在考虑使用此代码的边缘情况。如果承诺拒绝并且已经发生了对同一函数的第二次调用,那么它也将承诺拒绝。

答案 1 :(得分:0)

没有IIFE

let sharedLocalStreamPromise;

function getVideoStream() {
    return sharedLocalStreamPromise = sharedLocalStreamPromise || navigator.mediaDevices.getUserMedia(constraints);
};

与IIFE

const getVideoStream = (() => {
    let sharedLocalStreamPromise;
    return () => sharedLocalStreamPromise = sharedLocalStreamPromise || navigator.mediaDevices.getUserMedia(constraints);
})();

Alterntively

var getVideoStream = () => {
    const result = navigator.mediaDevices.getUserMedia(constraints);
    getVideoStream = () => result;
    return getVideoStream();
};

这最后一个在第一次调用时创建一个result(由getUserMedia返回的承诺),然后覆盖自己以返回该结果... {{1}的后续调用中没有条件 - 所以,理论上"更快" (在这种情况下,速度是一个没有实际意义的点)