【问题标题】:How to cancel a promise with $q in angular js如何在角度 js 中用 $q 取消承诺
【发布时间】:2019-10-17 01:53:45
【问题描述】:

我在下面有一个服务。每次打开模型时我都会调用此服务,当我关闭模型然后打开另一个模型时,以前的值会得到反映,在这种情况下,我想在每次关闭模型时取消承诺。

我试过下面的代码,

模型关闭.js

$scope.closeButton = function() {
    DetailDataSvc.storeDefer().resolve()
}

我的服务,(DetailDataSvc)

self.storeDefer = function() {
    return self.deferReturn;
};

self.getDetailReportData = function(postData, functionName) {
    var promises = {};

    var d = $q.defer(),
        metricDataType;
    self.deferReturn = $q.defer();
    promises = {
        detailReport: metricDataType,
        recommendedMetrics: DataSvc.getData(_logPrefix + functionName, recommendedMetricUrl),
        metricInfo: DataSvc.getData(_logPrefix + functionName, metricInfoUrl)
    };
    $q.all(promises).then(function(res) {
        $log.debug(_logPrefix + 'getDetailReportData(). Called from %s. $q.all Response (raw): ', functionName, res);
        else {
            if (response && !_.isEmpty(_.get(response, 'largeCard.chartData.dataValues.rows')) && response.overlayEnabled) {
                self.getMetricOverLay(pdata, functionName).then(function(overlayData) {
                    response.largeCard.chartData.overlay = overlayData;
                    d.resolve(response);
                }, function(msg, code) {
                    d.reject(msg);
                    $log.error(_logPrefix + 'getDetailReportData().   Error code: %s.  Error: ', code, msg);
                });
            } else {
                d.resolve(response);
            }
        }


    }, function(msg, code) {
        d.reject(msg);
        $log.error(_logPrefix + 'getDetailReportData().   Error code: %s.  Error: ', code, msg);
    });

    return d.promise;

};

谁能帮我看看我遵循的过程是否正确。

【问题讨论】:

标签: javascript angularjs promise angular-promise cancellation


【解决方案1】:

您尝试过的事情可能会起作用,但最好通过将$q.all() 返回的承诺与可拒绝的 Deferred(即 Deferred,其中引用保留其拒绝方法)竞争来解决,从而避免deferred anti-pattern.

self.getDetailReportData = function(postData, functionName) {
    var metricDataType = ......; // ???
    var d = $q.defer();

    // cancel previous
    if(self.cancelDetailReport) {
        self.cancelDetailReport(new Error('previous getDetailReportData() cancelled'));
    }
    // keep a reference to the deferred's reject method for next time round.
    self.cancelDetailReport = d.reject;

    var promises = {
        'detailReport': metricDataType,
        'recommendedMetrics': DataSvc.getData(_logPrefix + functionName, recommendedMetricUrl),
        'metricInfo': DataSvc.getData(_logPrefix + functionName, metricInfoUrl)
    };

    // Race aggregated `promises` against `d.promise`, thus providing the required cancellation effect.
    return $q.race([$q.all(promises), d.promise])
    .then(function(response) {
        // arrive here only if all promises resolve and d.reject() has not been called.
        $log.debug(_logPrefix + 'getDetailReportData(). Called from %s. $q.all Response (raw): ', functionName, response);
        if (response && !_.isEmpty(_.get(response, 'largeCard.chartData.dataValues.rows')) && response.overlayEnabled) {
            return self.getMetricOverLay(pdata, functionName)
            .then(function(overlayData) {
                response.largeCard.chartData.overlay = overlayData;
                return response;
            });
        } else {
            return response;
        }
    })
    .catch(function(msg, code) { // signature?
        // all error cases including cancellation end up here.
        var message = _logPrefix + `getDetailReportData().   Error: (${code}): ${msg}`; // or similar
        $log.error(message);
        throw new Error(message); // see https://stackoverflow.com/a/42250798/3478010
    });
};

注意事项:

  1. $q.race() 对赢得比赛的承诺是透明的,对另一个承诺是不透明的。因此,如果d$q.all() 返回的承诺解决之前被拒绝,那么d 将胜出; response 处理不会发生,d 的拒绝将落入.catch() 子句。或者,如果$q.all(promises) 返回的承诺胜出,则流程将遵循该承诺的成功路径(即response 处理)或可能的错误路径(将通过.catch() 子句)。

  2. 不太确定.catch() 回调的签名。您通常希望它接受单个 error 参数。

【讨论】:

  • 仅供参考 使用AngularJS V1.5.8,$q 服务现在也具有.race 方法。
  • @georgeawg,谢谢,这对这个练习有很大的影响。我会检查一下并编辑我的答案。
  • 编辑以适应$q.race(),感谢@georgeawg。
【解决方案2】:

分配已经创建延迟。 尝试更改此行:

self.deferReturn = $q.defer();

self.deferReturn = d;

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 2015-02-25
    • 2019-02-27
    • 2015-05-12
    • 1970-01-01
    相关资源
    最近更新 更多