Below, I have created a directive, which affects the parent scope and attaches each target button element(see oneClickOnly[attr.ocoId]).

The directive code is below

    angular.module('app').directive('oneClickOnly', [  
      '$parse', '$compile', function($parse, $compile) {
        return {
          restrict: 'A',
          scope: false, // get the parent scope directly
          compile: function(element, attr) {
            var fn = $parse(attr['oneClickOnly']);
            return {
              pre: function(scope, element, attr) {
                scope.oneClickOnly = scope.oneClickOnly || {}
                scope.oneClickOnly[attr.ocoId] = scope.oneClickOnly[attr.ocoId] || {}
                scope.oneClickOnly[attr.ocoId].fn = function(value) {
                  scope.oneClickOnly[attr.ocoId].val = value
                  if(value) {                
                    element.text(attr.ocoTextWait)
                    element.attr('disabled', true)
                  } else {
                    element.text(attr.ocoText)
                    element.attr('disabled', false)
                  }
                }
                var clickingCallback = function(e) {
                  if(scope.oneClickOnly 
                    && scope.oneClickOnly[attr.ocoId]
                    && scope.oneClickOnly[attr.ocoId].val) {
                    return
                  }              
                  scope.oneClickOnly[attr.ocoId].fn(true)
                  fn(scope, { $event: e });
                };
                element.bind("click", clickingCallback)
              }
            }
          }
        }
      }
    ])
`
**The html would change as below**  
_note - ng-click is not required_

    <md-button class="md-raised md-primary" oco-id="addCenter"  
      oco-text="Save" oco-text-wait="Saving" 
      one-click-only="doAsyncProcess()">

**The controller would be**

    onCompleteOfAsyncProcess() {  
      // addCenter should be same as oco-id
      $scope.oneClickOnly['addCenter'].fn(false)
    }