以下是我的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
};
答案 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}的后续调用中没有条件 - 所以,理论上"更快" (在这种情况下,速度是一个没有实际意义的点)