Cómo rechazar una promesa desde adentro y luego funcionar

85

Esta es probablemente una pregunta tonta, pero a mitad de la cadena de promesas, ¿cómo rechaza una promesa desde dentro de una de las funciones de then? Por ejemplo:

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

Ya no hay una referencia a la función original de resolver / rechazar o al PromiseResolver. ¿Se supone que debo agregar return Promise.reject(validationError);?

chinabuffet
fuente
1
throw validationError
kavun
> <Tenía la sensación de que sería algo tonto / fácil eso. Supongo que seguí pensando que tenía que llamar a una función de rechazo dedicada o devolver una Promesa fallida. Entonces, desde el interior de una promesa / thenable, ¿cualquier valor devuelto que no sea una nueva Promesa se considerará el valor resuelto? Y si arrojo un error, ¿es lo mismo que devolver una Promesa inmediatamente rechazada? Si publica eso como respuesta, lo aceptaré.
chinabuffet
Probablemente esté buscando la respuesta aceptada aquí stackoverflow.com/questions/17800176/…
crad

Respuestas:

96

¿Se supone que debo agregar return Promise.reject(validationError);?

Si. Sin embargo, es tan complicado solo en jQuery, con una biblioteca compatible con Promise / A + , también podría simplemente

throw validationError;

Entonces tu código se vería así

someActionThatReturnsAPromise()
    .then(modifyResource)
    .then(function(modifiedResource) {
        if (!isValid(modifiedResource))
            throw getValidationError(modifiedResource);
        // else !
        return modifiedResource;
    })
    .catch(function() {
        // oh noes
    });
Bergi
fuente
3
¿Es esto algo habitual? ¿Es ampliamente utilizado? Me siento mal haciéndolo, porque si .catchfalta algún lugar en el código , toda la aplicación explotará con un error irremediable ..
Andrey Popov
3
Tenga en cuenta que en una biblioteca compatible con Promise / A + puede usar throw porque el handlerfor thenes sincronización y la excepción puede detectarse. Si el controlador es asíncrono, debe devolver una promesa para eventualmente rechazarlo. Entonces, siempre devolver Promise.reject () en lugar de lanzar tiene sentido para mí. Porque si lanza un controlador asíncrono, la biblioteca no puede atraparlo y pasará silenciosamente. Tener cuidado.
Mike Gleason jr Couturier
1
@MikeGleasonjrCouturier: No debería haber manejadores asíncronos que no sean .thenmanejadores en una promesa :-) Si estás usando una API no promisificada, incluso return Promise.reject()te ayudará.
Bergi
@Bergi Quise decir como: p.then(function() { doAsync(function() { throw new Error("won't catch"); }); }); EDITAR: oh bien, releí tu comentario, estoy totalmente contigo, ¡estamos en la misma página! Quería señalarlo al OP :)
Mike Gleason jr Couturier
1
@MikeGleasonjrCouturier: Sí, eso es exactamente lo que estaba diciendo. Y doAsync(function() { return Promise.reject(new Error("won't catch, won't throw")); })tampoco funciona allí, simplemente falla silenciosamente. Realmente debería serlo doAsync().then(function() { throw new Error("will be caught"); })cuando trabajas con promesas.
Bergi