Javascript:如何在上一个函数的最终for循环完成后运行一个函数?

时间:2015-05-19 16:52:16

标签: javascript node.js for-loop

我正在编写一个Javascript函数,它将单词从CloudDB数据库中提取出来,并将它们放在三个数组中的一个中:动词,形容词或名词。一旦所有单词都到位并且最后一个循环运行,我想运行下一个函数。这是代码:

function verbnoun(array){
verbs = [];
adjectives = [];
nouns = []; 
for (i = 0; i<array.length; i++){
    //console.log(i);  <-- returns 0,1,2,3...57,58 as expected
    my_db.get(array[i], function(err, doc) {

        if (!err){
            if (doc.type == "verb"){

                verbs.push(doc.word);
            }
            else if (doc.type == "adjective"){

                adjectives.push(doc.word);
            }
            else if (doc.type == "noun"){

                nouns.push(doc.word);
            }


        }
        //console.log(i); <-- returns 59,59,59,59,59
        if (i+1 == array.length){
            nextFunction(verbs, adjectives, nouns);
        }       

    });
}

}

但是我无法弄清楚如何在最后一个循环之后运行下一个函数。如果我尝试在for循环之外运行它,我只是得到空数组。使用if语句在最后一个循环上触发似乎也不起作用,因为&#34; i&#34;在for循环中每次都停留在59,而不是从0,1,2,3等开始计数(参见代码中的注释),所以我不能指出哪个是最后一个循环。

这是我在StackExchange上的第一篇文章,感谢您的耐心等待。

2 个答案:

答案 0 :(得分:2)

你正在遭遇def main(): global Thread app = QtGui.QApplication(sys.argv) main = Main() Thread = RFID_Thread() Thread.rfid_event.connect(Main().on_event) Thread.start() sys.exit(app.exec_()) class Main(object): def __init__(self): self.accueil = MainWindow(self) self.access = AccessWindow() self.accueil.show() def on_event(self, data): # I WANT TO PAUSE THE QTHREAD HERE Thread.Pause = False ################################### # CHECKING DB & SHOWING UI # ################################### # AND RESUME IT HERE Thread.Pause = True class RFID_Thread(QtCore.QThread): rfid_event = pyqtSignal(str, name='rfid_event') Pause = True def run(self): while 1: if Pause: ser = serial.Serial(port=Serial_Port, baudrate=Serial_Baudrate) a = ser.read(19).encode('hex') ser.close() if len(a) <> 0: Code = a[14:] self.rfid_event.emit(Code) time.sleep(2) else: continue if __name__=='__main__': main() 的关闭,在i个任何一个get来电之前,它已经(可能)一直增加到59,并触发了他们的回调。

基本上,i表示发送的请求数,而不是已成功返回的请求数。您需要一个不同的计数器来跟踪该值。

&#13;
&#13;
function verbnoun(array) {
  verbs = [];
  adjectives = [];
  nouns = [];
  
  // New counter for completed requests
  var finished = 0;

  for (i = 0; i < array.length; i++) {
    //console.log(i);  <-- returns 1,2,3...57,58,59 as expected
    my_db.get(array[i], function(err, doc) {

      if (!err) {
        if (doc.type == "verb") {

          verbs.push(doc.word);
        } else if (doc.type == "adjective") {

          adjectives.push(doc.word);
        } else if (doc.type == "noun") {

          nouns.push(doc.word);
        }


      }
      //console.log(i); <-- returns 59,59,59,59,59
      if (++finished == array.length) {
        nextFunction(verbs, adjectives, nouns);
      }
    });
  }
}
&#13;
&#13;
&#13;

答案 1 :(得分:1)

你在那里遇到两个(或可能是三个)问题:

  1. for循环之后无法执行此操作的原因是get对数据库的调用还没有完成;他们是异步的。事实上,重要的是要记住,您的函数将在强的第一个get返回之前返回

  2. 您传递给i的回调中的
  3. get是变量i持久引用,而不是回调时的副本创建,这就是为什么你看到它总是59(数组长度)。

  4. 您的代码因未声明您的本地变量而成为The Horror of Implicit Globals的牺牲品。

  5. 请参阅有关如何解决该问题的评论:

    function verbnoun(array) {
        // Use var to declare your variables
        var verbs = [];
        var adjectives = [];
        var nouns = [];
    
        // Use a counter to remember how many responses you've had
        var responses = 0;
    
        // Schedule the calls
        for (var i = 0; i < array.length; i++) {
            // Call a function do do the work, passing in the index
            // for this loop
            doGet(i);
        }
    
        // Remember, your function returns at this point, before ANY
        // of the callbacks occurs
    
        // This function does the work
        function doGet(index) {
            // Because we're using `index`, not `i`, we get a value
            // for each call that won't change
            my_db.get(array[index], function(err, doc) {
    
                if (!err) {
                    if (doc.type == "verb") {
                        verbs.push(doc.word);
                    } else if (doc.type == "adjective") {
                        adjectives.push(doc.word);
                    } else if (doc.type == "noun") {
                        nouns.push(doc.word);
                    }
                }
    
                // Count this response
                ++responses;
    
                // If we have all of them, we're done
                if (responses == array.length) {
                    nextFunction(verbs, adjectives, nouns);
                }
            });
        }
    }
    

    虽然实际上,在这种特殊情况下,我们在回调中不需要index,因此我们并不需要将调用分离为构建函数。但它仍然可以很好地分清所发生的事情。