I have been using this method and it seems to work perfectly fine. This just waits for the time the cycle has finished and then triggers apply(). Simply call the function apply(<your scope>) from anywhere you want.
function apply(scope) {
if (!scope.$$phase && !scope.$root.$$phase) {
scope.$apply();
console.log("Scope Apply Done !!");
}
else {
console.log("Scheduling Apply after 200ms digest cycle already in progress");
setTimeout(function() {
apply(scope)
}, 200);
}
}