2013-05-28 2 views
22

Я написал этот маленький код в пользовательской службе в AngularJS.

В моей службе:

 var deferred = $q.defer(); 
     var promise = deferred.promise; 

     deferred.resolve('success'); 
     deferred.reject('error'); 

     /* Handle success and error */ 
     promise.success = function(fn) { 

      promise.then(function(response) { 

       fn(response); 

      }); 

      return promise; 
     }; 

     promise.error = function(fn) { 

      promise.then(null, function(response) { 

       fn(response); 

      }); 

      return promise; 
     }; 

В моем контроллере:

 promiseService.myPromise() 
      .success(function(data){ 

       $scope.success= data; 

      }) 
      .error(function(data){ 

       $scope.error = data; 

      }); 

Я Juste Ручки Успеха и ошибок от посыла (д сервиса $). Мне нужен этот код во множестве других сервисов, поэтому я бы просто предложил услугу $ q с обычаем.

Так что я хотел бы что-то подобное в моей службы:

var deferred = myPromiseService.$qCustom.defer(); 
    var promise = deferred.promise; 

    deferred.resolve('success'); 
    deferred.reject('error'); 

    return promise; 

Любая идея? Я нашел некоторое объяснение, чтобы расширить фильтр в Angularjs. Моя проблема заключается в том, чтобы найти хороший способ расширить все функциональные возможности $ q и добавить мои настройки.

я начинаю что-то вроде этого, это работа для обработки $ Q из коробки:

angular.module('myApp').service('myPromiseService', function($q){ 

    $qCustom = $q; 

}); 

ответ

26

Здесь вы найдете полное решение, в котором остановился @jessegavin.

var myApp = angular.module("myApp", []); 

myApp.config(function ($provide) { 

    $provide.decorator('$q', function ($delegate) { 
    var defer = $delegate.defer; 
    $delegate.defer = function() { 
     var deferred = defer(); 
     deferred.promise.success = function (fn) { 
     deferred.promise.then(function(response) { 
      fn(response.data, response.status, response.headers); 
     }); 
     return deferred.promise; 
     }; 
     deferred.promise.error = function (fn) { 
     deferred.promise.then(null, function(response) { 
      fn(response.data, response.status, response.headers); 
     }); 
     return deferred.promise; 
     }; 
     return deferred; 
    }; 
    return $delegate; 
    }); 

}); 
+0

Простой и работает, спасибо – Thomas

11

Если вы хотите изменить поведение по умолчанию то, что вводится с помощью угловой, вы можете использовать decorator() метод на службе $provide.

var myApp = angular.module("myApp", []); 

myApp.config(function ($provide) { 
    $provide.decorator("$q", function($delegate) { 
    // The $delegate argument here refers to the $q service. 

    $delegate.defer = function() { 
     alert("You just tried to call defer()!"); 
    }; 

    // Now, every time angular provides an instance of $q via 
    // injection, it will return your customized version of $q. 

    return $delegate; 
    }); 
}); 

Смотрите пример выше в действии на http://plnkr.co/edit/RuZF2cGkVHwlu7NIhxEZ?p=preview

Как модифицировать $q добавить функции успеха и ошибок, я не уверен, что на данный момент. Но я уверен, что именно здесь вы захотите это сделать.

3

ИМХО, украшение @jessegavin «s из $ Q не является совершенным, он не должен возвращать происхождения обещания в успехе & функции ошибки. Он потеряет возможность сгладить обратную пирамиду.

И он не может разделить данные отклика на успех & Функция ошибки $ httpPromise dose.

, например

//can't do this.. 
somePromise.success(function(){ 
    return $http.get(...)//another primise 
}).success(function(data){ 
    //data from $http.get.. 
}) 

Вот моя версия, она будет распознавать ответ HTTP и возвращает следующее обещание. Сделать свой собственный $ д имеет такое же поведение, как $ httpPromise

$provide.decorator('$q', function($delegate) { 
    function httpResponseWrapper(fn) { 
    return function(res) { 
     if (res.hasOwnProperty('data') && res.hasOwnProperty('status') && res.hasOwnProperty('headers') && res.hasOwnProperty('config') && res.hasOwnProperty('statusText')) { 
     return fn(res.data, res.status, res.headers, res.config, res.statusText); 
     } else { 
     return fn(res); 
     } 
    }; 
    }; 
    function decorator(promise) { 
    promise.success = function(fn) { 
     return decorator(promise.then(httpResponseWrapper(fn))); 
    }; 
    promise.error = function(fn) { 
     return decorator(promise.then(null, httpResponseWrapper(fn))); 
    }; 
    return promise; 
    }; 
    var defer = $delegate.defer; 
    $delegate.defer = function() { 
    var deferred = defer(); 
    decorator(deferred.promise); 
    return deferred; 
    }; 
    return $delegate; 
}); 
+0

Может быть, мое психическое двигатель JS не удается, но он читает мне, как это будет вести себя иначе, чем 'HttpPromise'. ['HttpPromise' должен вернуть оригинальное обещание] (http://stackoverflow.com/questions/16385278/angular-httppromise-difference-between-success-error-methods-and-thens-a), где это вернет новый обещание разрешить цепочку. – vossad01