Как связать условные обещания

Я изучаю 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();
        });
    }
}

Я знаком с async / await в C #, ни один из которых не вызывает проблем с условной цепочкой, но у меня проблемы с достижением того же с обещаниями.

Правильно ли ставить .then не сразу после создания обещания, а после if?

Возможно ли, что .then никогда не будет вызван, потому что обещание уже выполнено?


person Pak    schedule 19.01.2016    source источник
comment
Может быть, это лучше подходит для CodeReview?   -  person Script47    schedule 19.01.2016
comment
@ Script47 не совсем так. OP хочет помочь в добавлении дополнительных функций в свой код. Это было бы не по теме в Code Review.   -  person Kaz    schedule 19.01.2016
comment
@Zak OP, похоже, на самом деле не задал вопрос или не заявил, что у него есть какие-либо проблемы, за исключением того, что в заголовке, который звучит так же, как запрос на проверку кода.   -  person Alnitak    schedule 19.01.2016
comment
@Pak шаг, который вам не хватает, - это фактически return окончательное значение из любой .then цепочки [т.е. return promise.then(...) ]. Без этого вся функция немедленно вернется с уже определенным undefined значением.   -  person Alnitak    schedule 19.01.2016
comment
@Alnitak Ах, моя беда. Это была последняя фраза, которая меня сбила с толку. При повторном чтении вы оказались правы.   -  person Kaz    schedule 19.01.2016
comment
Это не лучший вопрос ни для одного сайта, ни здесь, ни в CR. То, что здесь не по теме, не означает, что это не по теме.   -  person Mast    schedule 19.01.2016
comment
Измените текст, включив в него очень конкретный вопрос. Прямо сейчас у вас есть широкое название и куча кода, а четких вопросов нет. Отсутствие четкого вопроса - почему вы получаете голоса против. Хороший вопрос будет включать описание того, какую конкретную проблему вы пытаетесь решить, что ваш текущий код делает, когда вы его выполняете, и с какой именно частью кода вам нужна помощь.   -  person jfriend00    schedule 19.01.2016


Ответы (2)


Можно объединять обещания в цепочку в любом порядке или использовать if, циклы и т. Д.

Если вы вызываете .then для обработанного обещания, оно будет выполнено мгновенно, так что это тоже нормально.
Единственный способ, которым 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;
})

or

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

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

Однако это может быть не лучшим решением.

Может быть более подходящим выполнить 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()
                    }); 
                }
            });
        }
    });
}
person Roamer-1888    schedule 20.01.2016