我有一个函数在不确定数量的项目中循环,并对每个项目进行异步调用以获取其他数据(html模板文件的内容)。回调做了一些检查。结果函数应该是可以的。 $ q是先前注入的,此代码是工厂的一部分。
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 :(得分: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'
});
});
}
答案 1 :(得分: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
};
}