如何做有条件的承诺链

时间:2016-01-19 15:05:10

标签: javascript angularjs typescript promise angular-promise

我正在学习promises / typescript / angular,我想有条件地链接承诺。

这是我方法的实际状态:

private executePromiseModificationEvenement<T>(edition: Models.CalendrierParametresModelEdition, modeCreation: boolean, deferred: ng.IDeferred<T>) {
    var promise: ng.IPromise<Object>;

    //Step1
    if (modeCreation) {
        promise = this.$calendrier.Actions.enregistrerEvenementOutlook(edition);
    } else {
        promise = this.$calendrier.Actions.modifierEvenementOutlook(edition);
    }

    if (this.$scope.outlook) {
        promise.then((x) => {
            if (x != '') edition.idOutlook = x.toString();;
            return deferred.resolve();
        }, (x) => {
            return deferred.reject();
        });
    } else {
        //Step2
        promise.then((x) => {
            if (x != '') edition.idOutlook = x.toString();
            return this.$calendrier.Actions.modifierEvenement(edition);
        }, (x) => {
            //Ajout MessageBox message error
            return this.$calendrier.Actions.modifierEvenement(edition);
        })
        //Step3
        .then((x) => {
            if (edition.opportunite != null) this.$rootScope.$broadcast("pushEchangeOpportunite", { idOpportunite: parseInt(edition.opportunite), action: 2, IdContact: edition.id, Libelle: edition.title, StartDate: moment(edition.start).toDate() });
            return deferred.resolve();
        }, (x) => {
            return deferred.reject();
        });
    }
}

我熟悉C#的async / await,这两种情况都没有给条件链接带来问题,但是我很难通过promises实现同样的目标。

在创建承诺之后但是在之后之后设置 .then 是否更正?

是否可能永远不会调用 .then ,因为承诺已经完成了?

2 个答案:

答案 0 :(得分:1)

将promises链接在任何顺序或使用ifs,loops等等都可以。

如果您在已解决的承诺上致电.then,它会立即执行,因此也很好。
如果承诺链永远不会被解决或被拒绝,那么不会被调用的唯一方法就是。

正常的链接方式可能是从函数中返回下一个对象。这比调用deferred.resolve()更简洁。

E.g。

var promise = this.$calendrier.Actions.enregistrerEvenementOutlook(edition);
promise = promise.then(function (x) {
    return 2 * x;
})
promise = promise.then(function (x) {
    return 2 * x;
})

var promise =
    this.$calendrier.Actions.enregistrerEvenementOutlook(edition)
    .then(function (x) {
        return 2 * x;
    })
    .then(function (x) {
        return 2 * x;
    })

答案 1 :(得分:1)

executePromiseModificationEvenement()不需要延期。传递一个绝对没有价值。相反,你应该寻找返回由函数中形成的promise链返回的promise。调用函数只需要稍作改动即可。

直截了当地,你的函数可以用一系列带有最终promise = promise.then(...)的(条件)return promise语句重写。一些代码重复也可以解决。

private executePromiseModificationEvenement<T>(edition: Models.CalendrierParametresModelEdition, modeCreation: boolean<T>) {
    var promise: ng.IPromise<Object>;
    promise = modeCreation ?
        this.$calendrier.Actions.enregistrerEvenementOutlook(edition) :
        this.$calendrier.Actions.modifierEvenementOutlook(edition);

    promise = promise.then((x) => {
        if (x != '') {
            edition.idOutlook = x.toString();
        }
    });

    if (!this.$scope.outlook) {
        promise = promise.then(() => {
            return this.$calendrier.Actions.modifierEvenement(edition);
        }, () => {
            return this.$calendrier.Actions.modifierEvenement(edition);
        })
        .then((x) => {
            if (edition.opportunite != null) {
                this.$rootScope.$broadcast("pushEchangeOpportunite", {
                    idOpportunite: parseInt(edition.opportunite), 
                    action: 2, 
                    IdContact: edition.id, 
                    Libelle: edition.title, 
                    StartDate: moment(edition.start).toDate() 
                }); 
            }
        });
    }
    return promise;
}

然而,这可能不是最好的解决方案。

可能更适合在链接结算期间而不是在链构建期间在if(this.$scope.outlook)被调用的位置执行this.$calendrier.Actions.modifierEvenement()...测试。结果不一定相同,因为this.$scope.outlook将有机会改变状态。

我个人认为,稍后执行测试 更合适(或无关紧要)。如果是这样,可以无条件地构建承诺链,并且内部执行所有测试,如果没有别的话,则更加整洁。

private executePromiseModificationEvenement<T>(edition: Models.CalendrierParametresModelEdition, modeCreation: boolean<T>) {
    return (modeCreation ? 
        this.$calendrier.Actions.enregistrerEvenementOutlook(edition) :
        this.$calendrier.Actions.modifierEvenementOutlook(edition))
    .then((x) => {
        if (x != '') {
            edition.idOutlook = x.toString();
        }
    })
    .catch((x) => { return x; }) // this mid-chain-error-recovery line is rather odd but consistent with the original code. It may be better placed one step earlier.
    .then(() => {
        if (!this.$scope.outlook) {
            return this.$calendrier.Actions.modifierEvenement(edition)
            .then(() => {
                if (edition.opportunite != null) {
                    this.$rootScope.$broadcast("pushEchangeOpportunite", {
                        'idOpportunite': parseInt(edition.opportunite),
                        'action': 2,
                        'IdContact': edition.id,
                        'Libelle': edition.title,
                        'StartDate': moment(edition.start).toDate()
                    }); 
                }
            });
        }
    });
}