How to cancel a promise with $q in angular js

时间:2019-05-31 11:56:54

标签: javascript angularjs promise angular-promise cancellation

I have a service below. I will call this service every time when I open a model and when I close the model and then open another one the previous values are getting reflected and in this case I want to cancel the promise every time I close the model.

I have tried the following code,

Model closing.js

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

My Service, (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;

};

Can anyone please help me whether the process I followed is the right one.

3 个答案:

答案 0 :(得分: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参数。

答案 1 :(得分:-1)

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

self.deferReturn = $q.defer();

self.deferReturn = d;

答案 2 :(得分:-1)

只需在要关闭模态时将其隐藏即可。