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

时间:2013-02-08 19:52:40

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

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

  1. 如果我过快地调用TTS功能​​,语音就会自行中断。
  2. 我的想法是编写一个信号量来检查音频是否正在播放,并且只有在完成后才会激活下一个命令。不幸的是:

    1. 如果我等到音频没有播放(audio.paused == true),程序会挂起/不会突破while循环。
    2. 有没有人对如何在不进入第二个问题的情况下解决第一个问题有任何想法?

      //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)
                  }
          })
          }
      

1 个答案:

答案 0 :(得分:3)

信号量用于多线程/ 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());

并且更清楚。