简体   繁体   English

如何做条件承诺链

[英]How to do conditional promise chaining

I'm learning promises/typescript/angular and I want to chain promises conditionally. 我正在学习Promise / TypeScript / Angular,我想有条件地链接Promise。

This is the actual state of my method: 这是我方法的实际状态:

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

I'm familiar of async/await of C#, neither of which gives a problem with conditional chaining, but I'm having trouble achieving the same with promises. 我对C#的异步/等待很熟悉,这两个都不会对条件链接产生任何问题,但是我在用promises实现相同的问题上遇到了麻烦。

Is it to correct to put a .then not just after the creation of the promise but after an if ? .the不仅放置在诺言创建之后而是放置在if之后, 是否正确

Is it possible that the .then may never be called because the promise is already finished? .then可能因为承诺已经完成而可能永远不会被调用吗?

It is fine to chain promises together in any order or use ifs, loops, whatever. 可以按任何顺序将诺言链接在一起,或者使用ifs,loops等等。

If you call .then on a resolved promise then it will execute instantly, so that's fine too. 如果按已解决的承诺调用.then ,那么它将立即执行,因此也可以。
The only way the then will not be called is if the promise chain is never resolved or is rejected. then不会被调用的唯一方法是promise链从未解决或被拒绝。

A normal way of chaining might be to return the next object from within the function. 链接的正常方法可能是从函数内返回下一个对象。 This tends to be neater than calling deferred.resolve() . 这往往比调用deferred.resolve()更整洁。

Eg 例如

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

or 要么

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

executePromiseModificationEvenement() doesn't need a Deferred. executePromiseModificationEvenement()不需要延迟。 There's absolutely no value in passing one in. Instead, you should be looking to return the promise returned by a promise chain formed within the function. 传递进来绝对没有任何价值。相反,您应该寻找返回函数内形成的承诺链返回的承诺。 The caller function(s) will need only a minor change. 调用方函数仅需进行很小的更改。

Straightforwardly, your function can be rewritten with a series of (conditional) promise = promise.then(...) statements with a final return promise . 直接地,您的函数可以使用一系列(条件) promise = promise.then(...)语句以及最终的return promise来重写。 Some of the code repetition can also be addressed. 某些代码重复也可以解决。

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

However, that may not be the best solution. 但是,这可能不是最佳解决方案。

It may be more appropriate to perform the if(this.$scope.outlook) test at the point where this.$calendrier.Actions.modifierEvenement()... is called, during chain settlement rather than during the chain building phase. 在链结算期间而不是在链构建阶段,在调用if(this.$scope.outlook) this.$calendrier.Actions.modifierEvenement()...的点执行if(this.$scope.outlook)测试可能更合适。 The result will not necessarily be the same because this.$scope.outlook will have had an opportunity to change state. 结果不一定相同,因为this.$scope.outlook将有机会更改状态。

Personally, I would guess that performing the test later is more appropriate (or inconsequential). 就个人而言,我猜想,进行测试后比较合适的(或无关紧要的)。 If so, the promise chain can be built unconditionally and all the tests performed internally, which if nothing else, is much tidier. 如果是这样,则可以无条件构建promise链,并在内部执行所有测试,如果没有别的话,则整洁得多。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM