¿Hay alguna forma de estructurar mejor el código? En particular, ¿cómo se manejan las excepciones dentro de una "cadena de promesas"?
$("#save").click(function(e) { e.preventDefault(); let $self = $(this); let profile = {} $self.prop("disabled", true) profile['oldPassword'] = $('#oldPassword').val(); profile['newPassword'] = $('#newPassword').val(); Profile.validateForm(profile).then(() => { Profile.sendAjax(profile).then(() => { $('#oldPassword').val(''); $('#newPassword').val(''); $("#profileAlert").text('Password changed successully').removeClass('alert-danger').addClass('alert-success').show().delay(5000).fadeOut() }).catch(e => { $("#profileAlert").text(e).removeClass('alert-success').addClass('alert-danger').show() }).finally(() => { $self.prop("disabled", false) }) }).catch(e => { $("#profileAlert").text(e).removeClass('alert-success').addClass('alert-danger').show() }).finally(() => { $self.prop("disabled", false) }) });Dado que su catch y finally las devoluciones de llamada se comportan de la misma manera, puede encadenar las promesas de manera segura:
Profile.validateForm(profile).then(() => { return Profile.sendAjax(profile); }).then(() => { $('#oldPassword').val(''); $('#newPassword').val(''); $("#profileAlert").text('Password changed successully').removeClass('alert-danger').addClass('alert-success').show().delay(5000).fadeOut() }).catch(e => { $("#profileAlert").text(e).removeClass('alert-success').addClass('alert-danger').show() }).finally(() => { $self.prop("disabled", false) })