javascript - Angular、Promises、foreach in textarea 以及保持处理顺序

标签 javascript html angularjs

我是 Angular 新手,但不是编程新手。尝试教老狗新把戏:)

我有一个文本区域,用户可以在其中输入要查找的字典单词列表。目前有 3 个地方通过 $http get 使用 API 并从 API 中提取响应。假设我在文本区域中有这些:

computer
fragment
teleport

它循环遍历文本区域并为每个单词运行“lookupWord()”。所有 3 个 API 结果都会合并起来,生成我自己的唯一 ID,并包含对象顶部的单词。这样我就可以将结果放入表中,并使表行的 (tr) id 成为我生成的唯一 ID。每行都有一个“查看”按钮,当他们单击它时,它会弹出一个包含所有详细信息的模式。这个过程使得匹配对象数组中的结果变得非常简单,尤其是在存在重复单词的情况下。

我的问题

我现在挂断,正在循环文本区域并保持处理顺序。当他们单击开始按钮时,我想禁用表单上的文本区域和复选框,这样在处理过程中就无法更改任何内容。完成后,需要解锁表单并提醒用户已完成。

我还没有让它禁用元素,但我试图让它在循环并查找每个单词后说“完成”。它在一切实际完成之前报告“完成”:(

这是一些代码:

HTML

<textarea ng-model="wordlistTextarea" ng-list="&#10;" 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/

相关文章:

javascript - 调整大小时,两个 div 相互穿过

javascript - 如何在 Vue 中取消选择可拖动的 svg 元素?

html - 如何使表格的两个单元格之间的边距为 0?

html - 如何放置页面的按钮(在顶部菜单栏中)特定图像?

jquery - 我可以将 angular-selectize 与 require.js 一起使用吗?

html - td 向上移动一个单元格

javascript - CEF Python ExecuteJavascript 不会设置输入元素的值

javascript - 在 Mongo 中查找包含 ISODate 字段的文档

javascript - 为什么我的进度条在开始加载之前显示完整的进度值

javascript - 从索引页 Angular 检查位置