2015-12-16 65 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