Last active
December 15, 2015 00:09
-
-
Save pdswan/5171174 to your computer and use it in GitHub Desktop.
What's the proper way to wrap a possibly asynchronous function in an angular deferred? I have an external, callback based SDK which interacts with an http API. The first time I ask for resources, an http call is made. The second time the data is cached so the callback is called immediately. This is a simplified example.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var data | |
function possiblyAsync(callback) { | |
if (alreadyLoaded) { | |
callback(data) | |
} else { | |
asyncLoad(function(loadedData) { | |
data = loadedData | |
callback(data) | |
}) | |
} | |
} | |
// results in digest already in progress | |
// when already loaded | |
function deferPossiblyAsync = function() { | |
var deferred = $q.defer() | |
possiblyAsync(function(data) { | |
$scope.$apply(function() { | |
deferred.resolve(data) | |
}) | |
}) | |
return deferred.promise | |
} | |
// works, but feels wrong | |
// referenced at | |
// http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply | |
function deferPossiblyAsync = function() { | |
var deferred = $q.defer() | |
possiblyAsync(function(data) { | |
if ($scope.$$phase) { | |
deferred.resolve(data) | |
} else { | |
$scope.$apply(function() { | |
deferred.resolve(data) | |
}) | |
} | |
}) | |
return deferred.promise | |
} | |
// UPDATE: | |
// does NOT work in all cases. woops. | |
// | |
// works and is cleaner, but "makes no guarantees as to when expression will be run" | |
// http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync | |
function deferPossiblyAsync = function() { | |
var deferred = $q.defer() | |
possiblyAsync(function(data) { | |
$scope.$evalAsync(function() { | |
deferred.resolve(data) | |
}) | |
}) | |
return deferred.promise | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
just run into this with 1.0.6, here's my stacktrace. can't reproduce it.
Error: $apply already in progress
at Error ()
at g (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:84:227)
at Object.e.$apply (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:88:362)
at e (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:94:424)
at o (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:98:3)
at XMLHttpRequest.s.onreadystatechange (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:99:131)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:99:195
at l (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:95:369)
at m (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:94:97)
at Function.m.(anonymous function) (http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js:96:278) angular.min.js:62
(anonymous function) angular.min.js:62
(anonymous function) angular.min.js:52
e.$apply angular.min.js:88
e angular.min.js:94
o angular.min.js:98
s.onreadystatechange angular.min.js:99
(anonymous function) angular.min.js:99
l angular.min.js:95
m angular.min.js:94
m.(anonymous function) angular.min.js:96
ConversationCtrl.$scope.switchConversationTo ctrl.conversations.js:280
ConversationCtrl.$scope.switchConversation ctrl.conversations.js:277
(anonymous function) angular.min.js:72
(anonymous function) angular.min.js:143
e.$eval angular.min.js:88
e.$apply angular.min.js:88
(anonymous function) angular.min.js:143
x.event.dispatch jquery.js:4692
y.handle jquery.js:4376
and thesea re my lines 279 to 281:
$scope.switchConversationTo = function($scope, conversation) {
$http.get('/s/conversations/read/'+conversation.objectId).success(function(result) {
}
when i had this error, the application was broken. clicking the button that calls this function would bring the error each time.