Como rejeitar uma promessa de dentro e então funcionar

85

Esta é provavelmente uma pergunta boba, mas no meio da cadeia de promessa, como você rejeita uma promessa de dentro de uma das funções then? Por exemplo:

someActionThatReturnsAPromise()
    .then(function(resource) {
        return modifyResource(resource)
    })
    .then(function(modifiedResource) {
        if (!isValid(modifiedResource)) {
            var validationError = getValidationError(modifiedResource);
            // fail promise with validationError
        }
    })
    .catch(function() {
        // oh noes
    });

Não há mais uma referência à função original de resolução / rejeição ou ao PromiseResolver. Devo apenas adicionar return Promise.reject(validationError);?

chinabuffet
fonte
1
throw validationError
kavun de
> <Tive a sensação de que seria algo bobo / fácil isso. Acho que fiquei pensando que tinha que chamar uma função de rejeição dedicada ou retornar uma promessa falhada. Portanto, dentro de uma promessa / obrigação, qualquer valor retornado que não seja uma nova promessa será considerado o valor resolvido? E se eu emitir um erro, isso é o mesmo que retornar uma promessa rejeitada imediatamente? Se você postar isso como uma resposta, eu aceito.
chinabuffet de
Você provavelmente está procurando a resposta aceito aqui stackoverflow.com/questions/17800176/...
crad

Respostas:

96

Devo apenas adicionar return Promise.reject(validationError);?

Sim. No entanto, é tão complicado apenas em jQuery, com uma biblioteca compatível com Promise / A +, você também pode simplesmente

throw validationError;

Então, seu código ficaria assim

someActionThatReturnsAPromise()
    .then(modifyResource)
    .then(function(modifiedResource) {
        if (!isValid(modifiedResource))
            throw getValidationError(modifiedResource);
        // else !
        return modifiedResource;
    })
    .catch(function() {
        // oh noes
    });
Bergi
fonte
3
É uma coisa normal a fazer? É amplamente utilizado? Eu me sinto mal fazendo isso, porque se algum lugar no código .catchestiver faltando, todo o aplicativo irá explodir com um erro inalterado.
Andrey Popov
3
Observe que em uma biblioteca compatível com Promise / A + você pode usar throw porque o handlerfor thené sync e a exceção pode ser detectada. Se o manipulador for assíncrono, ele terá que retornar uma promessa para rejeitar eventualmente. Portanto, sempre retornar Promise.reject () em vez de jogar faz sentido para mim. Porque se você lançar um manipulador assíncrono, a biblioteca não poderá detectá-lo e ele passará silenciosamente. Cuidado.
Mike Gleason jr Couturier
1
@MikeGleasonjrCouturier: Não deve haver manipuladores assíncronos que não sejam .thenmanipuladores sob uma promessa :-) Se você estiver usando uma API não prometida, o mesmo return Promise.reject()irá ajudá-lo.
Bergi
@Bergi eu quis dizer assim: p.then(function() { doAsync(function() { throw new Error("won't catch"); }); }); EDITAR: ah ok, eu reli seu comentário, estou totalmente com você, estamos na mesma página! Queria apontar isso para o OP :)
Mike Gleason jr Couturier
1
@MikeGleasonjrCouturier: Sim, é exatamente o que eu estava dizendo. E doAsync(function() { return Promise.reject(new Error("won't catch, won't throw")); })também não funciona lá - ele apenas falha silenciosamente. Realmente deveria ser doAsync().then(function() { throw new Error("will be caught"); })quando você está trabalhando com promessas.
Bergi