2017-01-16 25 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 
    }; 
}