javascript - 如何编写信号量检查两种不同的状态

标签 javascript jquery node.js text-to-speech semaphore

我正在使用文本转语音服务 (TTS) 来读取 Yelp API 的结果。我遇到了时间问题:

  1. 如果我太快调用 TTS 功能,语音会自行中断。

我的想法是编写一个信号量来检查音频是否正在播放,并且只有在完成后才将下一个命令显示为红色。不幸的是:

  1. 如果我等到音频不播放(audio.paused == true),程序就会挂起/不会跳出 while 循环。

有人知道如何解决第一个问题而不遇到第二个问题吗?

//check if command isn't already queued, and then add command to the queue
function voiceSynth (string, name) { 
if(voiceQueue.indexOf(string)== -1){
    voiceQueue.push(string) 
    voiceQueue.push(name) //used to keep track of the current item being read
}       
//Iterate over items in the queue
while (voiceQueue.length > 1){
    if (voiceBusy == false && audio.paused == true) {   
        voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift())
    }
    }
}
//ajax call to the TTS service
function voiceCall (string, name) {
    voiceBusy = true
    console.log('synth called on ' + string)
    $.ajax('read/?string=' + string + '&speed=' + speed, {
        type: 'GET',
        success: function(src) {
            audio.setAttribute('src', src)  
            audio.play()
            voiceBusy = false
            voiceCursor = name  
        },
        error: function(xhr, ajaxOptions, thrownError) {
            console.log(xhr)
            console.log(ajaxOptions)
            console.log(thrownError)
            }
    })
    }

最佳答案

信号量用于多线程/IPC 环境。使用 javascript 引擎,你就没有这个。您尝试在 Javascript 中轮询,这在单线程环境中不起作用,除非您使用 setTimeout 或 setInteval。

在您的设置中,您似乎有三种类型的事件:新的语音任务出现(并且应该排队)、Yelp AJAX 调用返回以及音频播放结束。您似乎已经处理了前两个事件,并且正在尝试找出如何处理音频结束事件。

我会将所有队列服务代码移至其自己的函数中,然后在发生有趣的事件时调用它。让队列服务代码弄清楚要做什么。其余代码只需处理事件并跟踪状态。像这样的东西可能会起作用:

    var ajaxOutstanding = false;
    var audioOutstanding = false;

    function voiceSynth(string, name) {
       if(voiceQueue.indexOf(string)== -1){
          voiceQueue.push(string) 
          voiceQueue.push(name) //used to keep track of the current item being read
       }
       serviceQueue();
    }

    //ajax call to the TTS service
    function voiceCall (string, name) {
        console.log('synth called on ' + string)
        $.ajax('read/?string=' + string + '&speed=' + speed, {
            type: 'GET',
            success: function(src) {
                ajaxOutstanding = false;
                audio.setAttribute('src', src);
                audioOutstanding = true;
                audio.play();
                voiceCursor = name;
                serviceQueue();
            },
            error: function(xhr, ajaxOptions, thrownError) {
                ajaxOutstanding = false;
                console.log(xhr);
                console.log(ajaxOptions);
                console.log(thrownError);
                serviceQueue();
            }
        });
    }

    function handleAudioEnded() {
        audioOutstanding = false;
        serviceQueue();
    }

    audio.addEventListener('ended', handleAudioEnded);

    function serviceQueue() {
        if (voiceQueue.length > 1 && !ajaxOustanding && !audioOutstanding) {
        voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift());
        }
    }

顺便说一下,

    voiceCall.call(undefined, voiceQueue.shift(),voiceQueue.shift());

相同
    voiceCall(voiceQueue.shift(), voiceQueue.shift());

而且更清晰。

关于javascript - 如何编写信号量检查两种不同的状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14780290/

相关文章:

javascript - 将页面内容滚动到鼠标滚动的自定义位置

javascript - 在 map Node.js 中使用 waterfall

css - 如何在通过 Express 发送的 HTML 文件中使用 CSS 和 JS 文件?

javascript - 您可以使用 WhatsApp API For Business 来验证用户吗?

javascript - 一般全局变量和 javaScript 中作为变量的对象之间的混淆

javascript - 使用 jQuery 和一些输入创建键/对对象

javascript - jQuery,在表中单击超链接值时将其从一个单元格复制到同一行中的另一个单元格

javascript - 如何从 PhantomJS 调用操作,我是否已经拥有足够的信息

javascript - 仅向列表中的第一个按钮添加功能

node.js - Mongoose 以 ddmmyyyy 格式保存日期