在Javascript / Node.JS中调用匿名函数时的堆栈顺序

时间:2016-12-09 21:33:45

标签: javascript node.js stack anonymous-function

使用匿名函数时,堆栈顺序如何在javascript中运行? 我希望打印下面的代码:“先打电话给第二个电话打三次电话”,但是打印出来:“第二个电话叫第三个电话”。

[{"name":"Abbey Road","parent":"Beatles","children":[{"name":"Come Together","parent":"Abbey Road"}, {"name":"Something","parent":"Abbey Road"},{"name":"Maxwell","parent":"Abbey Road"}, {"name":"Oh! Darling","parent":"Abbey Road"}]}]

非常感谢任何帮助。 感谢

2 个答案:

答案 0 :(得分:1)

不是匿名,而是异步会让你绊倒。你执行findTweets;执行T.get,最终将执行回调,并记录第二次调用&#39 ;;然后findTweets完成,所以你的脚本记录了第三次调用&#39 ;;最后,异步函数执行其回调,并记录首先调用'。

在调用异步函数之后,你不应该做任何取决于状态的事情"好像"异步功能已经完成,因为(正如你已经发现的那样)它经常不会有。

如果你有一个更复杂的情况,有些库可以帮助处理异步执行,例如async,或者你可以使用Promises。

答案 1 :(得分:1)

dmfay是正确的,异步的T.get()函数正在绊倒你。

查看MDN's write-up on the concurrency model

JavaScript从事件循环运行,从队列中处理消息。每条消息都与一个功能相关联。当堆栈具有容量时,将从队列中提取消息并进行处理。

每条消息都被处理完成,消息可以通过函数添加到队列中,包括将像T.get()函数一样异步处理的函数。在这种情况下,如果没有其他消息,则立即处理T.get(),但如果还有其他消息,例如console.log('third call'),则T.get()必须等待插入它消息进入堆栈,它必须等待它的回调完成才能调用console.log()。

function findTweets(params, num)
{
     params = {
        q: params, 
        count: num ,
        language: 'en' 
     }
     T.get('search/tweets', params, function(err, data, response) {
         console.log("first call"); // 3. Ok, I'm done!
        });

     console.log("second call"); // 4. Finally!
}
findTweets("a str",1) //1. I can start now but can't finish until my callbacks do
console.log("third call"); // 2. Sweet! I can go right now.

如何按照预期的顺序执行这些操作?尝试承诺和回调。

为了看到这一点,我用一个包含get()方法的对象来创建twitterAPI函数。 stubbed()方法使用setTimeout()

欺骗延迟响应
var twitterAPI = function () {
  this.get = function (method, params, callback) {
    setTimeout(function () {
      callback()
    }, 1000)
  }
}

var T = new twitterAPI()

function findTweets (params, num, callback) {
  params = {
    q: params,
    count: num,
    language: 'en'
  }

  var p1 = new Promise(function(resolve, reject) {
    T.get('search/tweets', params, function (err, data, response) {
      resolve("first call") // first call resolved as a promise
    })
  })

  p1.then(function(res) {
    console.log(res) // log resolved promise
    console.log("second call") // make second call
    return callback() // return callback so third call can go
  })
}

findTweets("a str", 1, function () {
  console.log("third call") // Finally, third call is called
})

/*
first call
second call
third call
*/