在 AngularJS 中使用 angular.forEach 实现异步等待

Posted

技术标签:

【中文标题】在 AngularJS 中使用 angular.forEach 实现异步等待【英文标题】:Implement async await using angular.forEach in AngularJS 【发布时间】:2020-03-23 03:08:39 【问题描述】:

我正在尝试使用 api 保存所选项目列表的标签。在 api 中,我只为第一个选定的项目存储标签一次,其余的我不存储项目,而是将条目创建为共享。 问题是:第一个选定的项目命中 api,在存储数据之前,其他选定的项目也被命中,我无法提供共享引用,因为数据尚未存储。

我尝试过的事情 -

这是我的控制器:

let selectedQstCount = $scope.selectedQuestion.length;
for (i = 0; i < selectedQstCount; i++) 
    var params = 
        "jsonString": callbackData,
        "questionNo": $scope.Questionlst.find(a => a.QuestionId == $scope.selectedQuestion[i].id).QuestionNo,
        "projectName": $scope.ProjectName,
        "projectId": $scope.ProjectId,
        "questionId": $scope.selectedQuestion[i].id,
        "newCodeFrame": ($scope.attachCodeFrame == "No" ? "FALSE" : "TRUE"),
        "sharedQstId": $scope.sharedQstId,
        "groupName": $scope.groupName
    
    var defer = $q.defer();
    CodeFrameJsonfactory.CodeFrameUpload(params, function (data) 
        //success
        $q.resolve(data);
    , function (callbackData) 
        //error
        inform.clear();
        inform.add(callbackData.Message,  ttl: -1, type: 'danger' );
    );
    return defer.promise;

这是我的工厂:

CodeFrameUpload: function (params, successCallback, errorCallback) 
    var deferred = $q.defer();
    $http(
        method: 'POST',
        url: APIUrls.getUrl("uploadCodeFrame"),
        data: params,
        headers: 
            'Content-Type': 'application/json'
        ,
        cache: false
    ).success(function (data) 
        deferred.resolve(data);
        successCallback(data);
    ).error(function (data) 
        deferred.reject(data);
        errorCallback(data);
    );
    return deferred.promise;
,

我也尝试过使用带有延迟的 angular.forEach。

我要实现的是,在CodeFrameUpload函数完成之前我不想再点击它。

【问题讨论】:

.success 方法一直是removed from the AngularJS framework。 【参考方案1】:

返回一个数据承诺:

CodeFrameUpload: function (params) 
    return $http(
        method: 'POST',
        url: APIUrls.getUrl("uploadCodeFrame"),
        data: params,
        headers: 
            'Content-Type': 'application/json'
        ,
        cache: false
    ).then(function(response) 
        return response.data;
    );
,

映射返回的承诺:

var promiseArr = $scope.selectedQuestion.map(question => 
    var params = 
        "jsonString": callbackData,
        "questionNo": $scope.Questionlst.find(a => a.QuestionId == question.id).QuestionNo,
        "projectName": $scope.ProjectName,
        "projectId": $scope.ProjectId,
        "questionId": question.id,
        "newCodeFrame": ($scope.attachCodeFrame == "No" ? "FALSE" : "TRUE"),
        "sharedQstId": $scope.sharedQstId,
        "groupName": $scope.groupName
    
    return CodeFrameJsonfactory.CodeFrameUpload(params);
);

使用$q.all

$q.all(promiseArr).then(function(dataArr) 
    console.log(dataArr);
).catch(function(errResponse) 
    console.log(errResponse);
);

$q.all 返回一个单一的承诺,该承诺将通过值的数组/散列解析,每个值对应于承诺数组/散列中相同索引/键处的承诺。如果任何一个 Promise 以一个拒绝的方式解决,这个产生的 Promise 将以相同的拒绝值被拒绝。

有关详细信息,请参阅

AngularJS $q Service API Reference - $q.all

更新

以上示例并行执行 HTTP 请求。

按顺序链接承诺:

var paramsArr = $scope.selectedQuestion.map(question => (
        "jsonString": callbackData,
        "questionNo": $scope.Questionlst.find(a => a.QuestionId == question.id).QuestionNo,
        "projectName": $scope.ProjectName,
        "projectId": $scope.ProjectId,
        "questionId": question.id,
        "newCodeFrame": ($scope.attachCodeFrame == "No" ? "FALSE" : "TRUE"),
        "sharedQstId": $scope.sharedQstId,
        "groupName": $scope.groupName
));

var sequentialPromise = paramsArr.reduce( (promise, paramsObj) => 
    promise.then(function(dataArr) 
        var singlePromise = CodeFrameJsonfactory.CodeFrameUpload(paramsObj);
        return $q.all([...dataArr, singlePromise]);
    ,
    $q.when([])
);

sequentialPromise.then(function(dataArr) 
    console.log(dataArr);
);

【讨论】:

我认为 .map .forEach 不是同步调用 ajax 的正确方法。它一次击中了api。必须有其他方式。 更新了答案以显示链接顺序承诺的示例。

以上是关于在 AngularJS 中使用 angular.forEach 实现异步等待的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AngularJS 中使用 HTTPS?

如何使用 angularjs 在 RESTful 请求中执行授权?

在 AngularJS 中使用引导工具提示

在 MVC VIEW 中使用 AngularJS/AJAX 呈现后端数据

AngularJS学习篇

无法在 Angularjs 中使用 templateUrl 加载模板