我是 Angular 新手,但不是编程新手。尝试教老狗新把戏:)
我有一个文本区域,用户可以在其中输入要查找的字典单词列表。目前有 3 个地方通过 $http get 使用 API 并从 API 中提取响应。假设我在文本区域中有这些:
computer
fragment
teleport
它循环遍历文本区域并为每个单词运行“lookupWord()”。所有 3 个 API 结果都会合并起来,生成我自己的唯一 ID,并包含对象顶部的单词。这样我就可以将结果放入表中,并使表行的 (tr) id 成为我生成的唯一 ID。每行都有一个“查看”按钮,当他们单击它时,它会弹出一个包含所有详细信息的模式。这个过程使得匹配对象数组中的结果变得非常简单,尤其是在存在重复单词的情况下。
我的问题
我现在挂断,正在循环文本区域并保持处理顺序。当他们单击开始按钮时,我想禁用表单上的文本区域和复选框,这样在处理过程中就无法更改任何内容。完成后,需要解锁表单并提醒用户已完成。
我还没有让它禁用元素,但我试图让它在循环并查找每个单词后说“完成”。它在一切实际完成之前报告“完成”:(
这是一些代码:
HTML
<textarea ng-model="wordlistTextarea" ng-list=" " ng-trim="false" class="form-control" id="wordsTextarea" placeholder="words to research..." rows="10"></textarea>
<input ng-model="checkboxSources.webster" type="checkbox" id="webster-api"> Merriam Webster (Dictionary API)
<input ng-model="checkboxSources.oxford" type="checkbox" id="oxford-api"> Oxford American College Dictionary (Google)
<input ng-model="checkboxSources.forvo" type="checkbox" id="forvo-api"> Forvo Pronunciation Dictionary
<button ng-disabled="!wordlistTextarea" ng-click="startProcessing()" class="btn btn-success" id="pronunciation-submit" preventDefault>Search</button>
JS
$scope.searchResults = []; // holds array of objects for later use
$scope.baseApiUri = 'http://apibase.com/api/here';
$scope.checkboxSources = {
webster : true,
oxford : true,
forvo : true
};
$scope.startProcessing = function() {
var promises = [];
angular.forEach($scope.wordlistTextarea, function(value, key){
//$scope.lookupWord(value.trim());
promises.push($scope.lookupWord(value.trim()));
});
$q.all(promises).then(function(results) {
console.dir(results);
})
.then(function(data) {
console.log('DONE!!');
});
};
$scope.lookupWord = function($word) {
Q.all([$scope.getWebster($word), $scope.getOxford($word), $scope.getForvo($word)])
.spread(function (resultWebster, resultOxford, resultForvo) {
var randomId = $scope.getRandomId();
var result = {
'word': $word,
'id': randomId,
'sources': {
'webster': resultWebster.data,
'oxford': resultOxford.data,
'forvo': resultForvo.data,
},
};
$scope.addToResults(result);
})
.done();
};
$scope.downloadPart = function(myUrl) {
return $http({
method: 'GET',
url: myUrl,
});
};
$scope.addToResults = function(data) {
console.log('Adding Result:');
console.dir(data);
$scope.searchResults.push(data);
};
// -- API SOURCES --
$scope.getWebster = function(word) {
if ( $scope.checkboxSources.webster == true ) {
var url = $scope.baseApiUri + '/dictionary?word=' + word;
return $scope.downloadPart(url);
} else {
return null;
}
};
$scope.getOxford = function(word) {
if ( $scope.checkboxSources.oxford == true ) {
var url = $scope.baseApiUri + '/oxford?word=' + word;
return $scope.downloadPart(url);
} else {
return null;
}
};
$scope.getForvo = function(word) {
if ( $scope.checkboxSources.forvo == true ) {
var url = $scope.baseApiUri + '/forvo?word=' + word;
return $scope.downloadPart(url);
} else {
return null;
}
};
概述
同样,我的问题是当我单击“startProcessing”按钮时,它需要先执行一些操作(禁用表单),循环遍历文本区域并查找单词。完成后,我需要做更多的事情(例如启用表单上的元素、提醒完成!等)。
此外,我想用 Angular 中包含的 $q 替换 Q
(我已经包含了该库)。我使用Q
,因为它具有传播
。正如您所看到的,我使用 spread 将结果专门放入对象中。我不知道是否可以使用 $q.all()
代替并使用 $result[0]、$result[1] 等
?
有任何问题请告诉我。我写这篇文章的速度很快,因为我要和 children 一起玩“不给糖就捣蛋”的游戏:)
提前致谢!
PS:请随意纠正我错误的 Angular,或者我应该如何做得更好(或正确)。这是学习和变得更好的唯一途径;)
最佳答案
问题是 Promise 数组实际上并不是 promise
数组。
您的 lookupWord
函数需要返回它创建的 Promise,以便可以对其进行监视。
只需为其创建的 promise 添加一个返回
即可。
$scope.lookupWord = function($word) {
return Q.all([$scope.getWebster($word), $scope.getOxford($word), $scope.getForvo($word)])
.spread(function (resultWebster, resultOxford, resultForvo) {
var randomId = $scope.getRandomId();
var result = {
'word': $word,
'id': randomId,
'sources': {
'webster': resultWebster.data,
'oxford': resultOxford.data,
'forvo': resultForvo.data,
},
};
$scope.addToResults(result);
})
.done();
};
关于javascript - Angular、Promises、foreach in textarea 以及保持处理顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40350796/