Yes, in my helper JS file I have utility function to provide me Actions as promises for this very reason.
Snippet below and full code at https://gist.github.com/DouglasCAyers/13db5714c3cae0cbcacd252fba8c127a#file-controller-js-L2
callAction : function( component, actionName, params ) {
var helper = this;
var p = new Promise( function( resolve, reject ) {
helper.showSpinner( component );
var action = component.get( actionName );
if ( params ) {
action.setParams( params );
}
action.setCallback( helper, function( response ) {
helper.hideSpinner( component );
if ( component.isValid() && response.getState() === 'SUCCESS' ) {
resolve( response.getReturnValue() );
} else {
console.error( 'Error calling action "' + actionName + '" with state: ' + response.getState() );
reject( response.getError(), response.getState() );
}
});
$A.enqueueAction( action );
});
return p;
},
Then in my controller JS or other helper JS functions I can call and chain actions together like this:
someMethod : function( component, event, helper ) {
var helper = this;
helper.callAction( component, 'c.someApexMethod', {
'someParam' : component.get( 'v.someAttribute' )
}).then( $A.getCallback( function( data ) {
component.set( 'v.anotherAttribute', data );
})).catch( $A.getCallback( function( errors, state ) {
helper.logActionErrors( component, errors );
}));
}
You may also be interested in Bob Buzzards blog post about same topic: http://bobbuzzard.blogspot.com/2016/12/javascript-promises-in-lightning_30.html
executeAction
from JavaScript Promises in Lightning Components to a base component for now?