【问题标题】:How to do conditional promise chaining如何进行有条件的承诺链
【发布时间】:2016-04-25 03:01:00
【问题描述】:

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

这是我的方法的实际状态:

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 很熟悉,这两者都没有给条件链接带来问题,但我在使用 Promise 时遇到了麻烦。

.then 不仅放在创建承诺之后而且放在 if 之后是否正确?

.then 有没有可能因为 promise 已经完成而永远不会被调用?

【问题讨论】:

  • 也许这更适合CodeReview
  • @Script47 不完全是。 OP 希望帮助为其代码添加额外的功能。那将是代码审查的题外话。
  • @Zak OP 实际上并没有提出问题或表示他有任何问题,除了标题中的内容,这听起来就像代码审查请求。
  • @Pak 您缺少的步骤实际上是return 来自任何.then 链的最终值[即return promise.then(...) ] 没有那个,整个函数将返回一个已经解析的@987654326立即@值。
  • @Alnitak 啊,我的错。这是最后一句话让我震惊。重新阅读后,您似乎是正确的。

标签: javascript angularjs typescript promise angular-promise


【解决方案1】:

executePromiseModificationEvenement() 不需要延迟。传入一个绝对没有任何价值。相反,您应该寻求返回由函数内形成的承诺链返回的承诺。调用函数只需稍作改动。

简单地说,您的函数可以用一系列(有条件的)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;
}

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

在链结算期间而不是在链构建阶段,在调用this.$calendrier.Actions.modifierEvenement()... 的点执行if(this.$scope.outlook) 测试可能更合适。结果不一定相同,因为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()
                    }); 
                }
            });
        }
    });
}

【讨论】:

    【解决方案2】:

    可以以任何顺序将 Promise 链接在一起,或者使用 ifs、循环等。

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

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

    例如

    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;
        })
    

    【讨论】:

      猜你喜欢
      • 2018-02-25
      • 2021-08-01
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 2016-01-07
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多