setTimeout的递归函数

时间:2015-12-16 21:51:03

标签: javascript node.js

我使用递归函数从外部源获取数据,处理它并在必要时进行其他调用。

我需要在连续多次调用此外部源之前暂停。

在调用我的" final"之前,如何确保我拥有外部资源的所有结果?功能

function showAll(results) {
    console.log('All done, time for doing something else with results')
    console.log(results)
}

function checkName(person) {
    console.log('checking name of ' + person.name)
    if (person.name === 'Julie') return true 
}

function checkPersons(url) {
        // Do something here to get new data from an external source
    var data = {
        // 'goAgain': https://newUrl.com,
        'results': [
          {name: 'Bob', age: 21},
          {name: 'Frank', age: 15, go: 1},
          {name: 'Julie', age: 12}
        ]
    }

    var persons = data.results
    var results = []

    persons.forEach(function(person, i) {
        if (person.age >= 18) {
            console.log('do not need to check name of ' + person.name)
            results.push(person)
        } else {
            setTimeout(function() {
                if (checkName(person)) {
                    console.log('Julie is ' + person.name)
                    results.push(person)
                }
            }, 5000 * i)
        }        
    })

    if (data.goAgain) {
      // Go back and call the function again to get the 
      // next set of results from external source
      // checkPersons(goAgain)
      console.log('Calling the function again to get more results if necessary')
    } else {
      // But, checkName is still running because of setTimeout
      // so results doesn't yet have everything we need
      showAll(results)
    }
}

checkPersons('https://someurl.com')

https://jsfiddle.net/nicholasduffy/28Lpsgbj/3/

do not need to check name of Bob
// No, clearly not all done because we haven't checked Frank or Julie yet   
(index):27 All done, time for doing something else with results
// Just Bob
(index):28 [Object]
(index):32 checking name of Frank
(index):32 checking name of Julie
(index):57 Julie is Julie
// Now I really want results

1 个答案:

答案 0 :(得分:1)

您需要处理等待异步操作。一个好方法是使用Promises。此外,即使您不需要等待setTimeout,也可以像处理所有一样。这使您的流程更容易维护:

var promises = persons.map(function(person, i) {
    return new Promise(function(resolve, reject) {
        if (person.age >= 18) {
            console.log('do not need to check name of ' + person.name)
            results.push(person);
            return resolve();
        }
        setTimeout(function() {
            if (checkName(person)) {
                console.log('Julie is ' + person.name)
                results.push(person);
            }
            resolve();
        }, 5000 * i)
    });
})

Promise.all(promises)
    .then(function() {
        if (data.goAgain) {
            // Go back and call the function again to get the 
            // next set of results from external source
            // checkPersons(goAgain)
            console.log('Calling the function again to get more results if necessary')
        } else {
            // But, checkName is still running because of setTimeout
            // so results doesn't yet have everything we need
            showAll(results)
        }
    });