2017-01-16 43 views
0

我有一個函數,通過不確定數量的項目進行循環,並對每個項目進行異步調用以獲取其他數據(html模板文件的內容)。回調做了一些檢查。由此產生的功能應該是可以接受的。 $ q是更早注入的,這個代碼是工廠的一部分。AngularJS將變量傳遞到循環異步回調

function searchHelpTopics(topics, searchPhrase) { 
    if (topics == null || topics.length == 0) return "No search results"; 
    var results = []; 
    var promises = []; 
    for (var i = 0; i < topics.length; i++) { 
     var templateURL = topics[i].URL; 
     var topic = topics[i]; 
     if (topics[i].HelpTopicId != "Search") { 
      var promise = $templateRequest(templateURL).then(function (template) { 
       var text = HTMLToText(template, true); 
       // do the search 
       if (text.indexOf(searchPhrase) > -1) { 
        if (text.length > 50) text = text.substring(0, 50); 
        var result = {}; 
        result.title = topic.Title; 
        result.excerpt = text; 
        result.helpID = topic.HelpTopicID; 
        results.push(result); 
       } 
      }); 
      promises.push(promise); 
     } 
    } 
    return $q.all(promises).then(function() { 
     return results; 
    }) 

的這裏的問題是,for循環不會等待回調明顯,因此正在使用的回調題目是不是正確的。我需要一種將主題傳遞到每個循環回調的方法。

+0

[JavaScript閉合內循環 - 簡單實用示例]的可能重複(http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-pract ical-example) – 4castle

回答

1

因爲JS只有函數範圍,所以你可以重寫你的代碼來使用函數而不是'for'循環(這通常更好)。

要做到這一點,您可以使用JS內置的forEach(從版本1.6開始,幾乎適用於所有瀏覽器)或良好的功能樣式庫(如underscore.js或lodash.js)。

甚至更​​好 - 使用Array.map和Array.filter - 看到代碼

function processTemplate(topic, template) { 
 
    var text = HTMLToText(template, true); 
 
    // do the search 
 
    if (text.indexOf(searchPhrase) < 0) { 
 
    return; 
 
    } 
 
    if (text.length > 50) { 
 
    text = text.substring(0, 50); 
 
    } 
 
    return { 
 
    title: topic.Title, 
 
    excerpt: text, 
 
    helpID: topic.HelpTopicID 
 
    }; 
 
} 
 

 
function searchHelpTopics(topics, searchPhrase) { 
 
    if (!topics || topics.length === 0) { 
 
    return "No search results"; 
 
    } 
 
    var promises = topics 
 
    .filter(function(topic) { return topic.HelpTopicId !== "Search"; }) 
 
    .map(function(topic) { 
 
     return $templateRequest(topic.URL).then(processTemplate); 
 
    }); 
 
    return $q.all(promises) 
 
    .then(function (results) { 
 
     return results.filter(function (result) { 
 
     return result; // filters out 'undefined' 
 
     }); 
 
    }); 
 
}

+0

謝謝我喜歡這種方法,但它不起作用,因爲主題和searchPhrase都不會傳入processTemplate。我會嘗試使用forEach next ... – nuander

+0

我能夠通過替換 返回$ templateRequest(topic.URL).then(processTemplate); with return $ templateRequest(topic.URL).then(function(template){ processTemplate(template,topic,searchPhrase); }); 但結果是一個空數組,當它應該有3個結果 – nuander

+0

得到它的工作。我已經添加了工作代碼的答案。 – nuander

0

的不是一個完整的解決方案,但足以說明它是如何工作

somefactory.getHelpTopics().then(function (topics) { 
    somefactory.searchHelpTopics(topics, searchText).then(function (searchResults) { 
     vm.searchResults = searchResults; 
     vm.helpID = "Search"; 
    }); 
}); 

--- some factory functions ---- 
function searchHelpTopics(topics, searchPhrase) { 
    if (!topics || topics.length === 0) return "No search results"; 
    var promises = topics 
     .filter(function (topic) { return topic.HelpTopicId !== "Search"; }) 
     .map(function (topic) { 
      return $templateRequest(topic.URL).then(function (template) { 
       return searchHelpTemplate(template, topic, searchPhrase); 
      }); 
     }); 
    return $q.all(promises).then(function (results) { 
     return results.filter(function (result) { 
      return result; // filters out 'undefined' 
     }); 
    }); 
} 
function searchHelpTemplate(template, topic, searchPhrase) { 
    var text = HTMLToText(template, true); 
    // do the search 
    if (text.indexOf(searchPhrase) < 0 && topic.Title.indexOf(searchPhrase) < 0) { 
     return; 
    } 
    if (text.length > 50) { 
     text = text.substring(0, 50); 
    } 
    return { 
     title: topic.Title, 
     excerpt: text, 
     helpID: topic.HelpTopicId 
    }; 
}