Как синхронизировать обратные вызовы getUserMedia в синглтоне

Я использую Singleton, чтобы получить аудио-рекордер, но getUserMedia является асинхронным, и я должен дождаться окончания обратных вызовов, чтобы вернуть объект рекордера. Возможно, это не лучший выбор для смешивания синхронного и асинхронного, но я не вижу, как я могу это сделать, потому что не могу сделать getUserMedia синхронным.

Идея состоит в том, чтобы вызвать SoundRecorder.getInstance(), который попросит пользователя разрешить доступ к микрофону один для всех и иметь возможность получить экземпляр рекордера в любое время, когда мне нужно.

Проблема при первом звонке:
var рекордер = SoundRecorder.getInstance();
значение рекордера "неопределено", тогда оно отлично работает для других вызовов.

Это мой код ниже. Спасибо за вашу помощь.

var SoundRecorder = (function () {

var instance = null;

function init () {

    var dfd = $.Deferred();

    if (instance == null) {
        navigator.getUserMedia({audio: true},
            function(stream) {
                var audioContext = new AudioContext();
                var input = audioContext.createMediaStreamSource(stream);
                console.log('Media stream created.');

                input.connect(audioContext.destination);
                console.log('Input connected to audio context destination.');

                instance = new Recorder(input);
                dfd.resolve('recorder created');

            },
            function (e) {
                dfd.reject('No live audio input');
                notify('error', 'No live audio input: ' + e);
            });
    } else {
        dfd.resolve('recorder already created');
    }
    return dfd.promise();
}

function waitFor(p){
    if (p.state() == "resolved" || p.state() == "rejected") {
        return instance;
    } else {
        setTimeout(waitFor, 500, p);
    }
}

return {
    getInstance: function() {
        var promise = init();

        promise.then(function () {
            console.log('init success');
        }, function () {
            console.log('init failed');
        });

        return waitFor(promise);
    }
}

}) ();

1 ответ

Решение

Наконец, я отказался от использования синглтона, чтобы использовать только обратные вызовы. Я сделал трюк, чтобы просто вызвать getUserMedia один раз со скрытым полем ввода, которое я использую для обработки другого статуса: "включено", если пользователь разрешил доступ к микрофону, "отключено", если веб-аудио не поддерживается, "доступ", когда доступ спросил пользователя. Я думаю, что не так элегантно, но это работает. Я надеюсь, что это может помочь кому-нибудь однажды;-)

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