2015-12-16 66 views
1

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

我需要在连续调用这个外部源之前暂停。

在调用我的“最终”函数之前,如何确保从外部资源获得所有结果?

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 
+0

您是否期望服务器发送某种完成信号? – markthethomas

+0

我期待检查data.goAgain的存在。如果它在那里,我知道我将需要至少再打一个电话。如果它不在那里,我知道这是我的最后一次电话。 – duffn

+0

很酷。因此,如果您要依赖外部数据生产者来告诉您何时获得您需要的所有数据,那么它必须是发送该数据的那个人。你想知道如何设置'data.goAgain'属性吗? :) – markthethomas

回答

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) 
     } 
    }); 
+0

谢谢,这会让我走上正轨。 – duffn