Angularjs Cannot get the correct data from a service in a controller

I try to build a mobile app with Ionic/Angular/Cordova, and I have some problems with a service :) My code looks like this :

SERVICE:

    'use strict';
    angular.module('MyDemoApp.services').service('ImageService', function($cordovaCamera, $cordovaFile) {
  // 1
  //$scope.images = [];       
   this.addImage = function (method){
        var imageDetails ={'name':'', 
                           'src':''
                          };
        // 2
        // Set the "options array" [who is passed to the cordovaCamera] by method [take | choose]
        // Docs : http://plugins.cordova.io/#/package/org.apache.cordova.camera
        var options ={};
        if (method==='take'){
            options = {
              destinationType : Camera.DestinationType.FILE_URI,
              sourceType : Camera.PictureSourceType.CAMERA, 
              allowEdit : false,
              encodingType: Camera.EncodingType.JPEG,
              popoverOptions: CameraPopoverOptions,
            };
        } else if (method==='choose'){
            options = {
              destinationType : Camera.DestinationType.FILE_URI,
              sourceType : Camera.PictureSourceType.PHOTOLIBRARY,
              allowEdit : false,
              encodingType: Camera.EncodingType.JPEG,
              popoverOptions: CameraPopoverOptions,
            };
        }

        // 3
        // Call the ngCodrova module cordovaCamera we injected to our service.
        $cordovaCamera.getPicture(options).then(function(imageData) {
                      // 4
                      // When the image capture returns data, we pass the information to our success function, 
                      // which will call some other functions to copy the original image to our app folder.
                      onImageSuccess(imageData);

                      function onImageSuccess(fileURI) {
                        createFileEntry(fileURI);
                      }

                      function createFileEntry(fileURI) {
                        window.resolveLocalFileSystemURL(fileURI, copyFile, fail);
                      }

                      // 5
                      // This function copies the original file to our app directory. 
                      // We have to deal with duplicate images, we give a new name to the file consisting of a random string and the original name of the image.
                      function copyFile(fileEntry) {
                        var name = fileEntry.fullPath.substr(fileEntry.fullPath.lastIndexOf('/') + 1);
                        var newName = makeid() + name;

                        window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function(fileSystem2) {
                          fileEntry.copyTo(
                            fileSystem2,
                            newName,
                            onCopySuccess,
                            fail
                          );
                        },
                        fail);
                      }

                      // 6
                      // If the copy task finishes successful, we push the image url to our scope array of images. 
                      // Make sure to use the apply() function to update the scope and view!
                      function onCopySuccess(entry) {
                        window.alert('success');
                        imageDetails.name=entry.name;
                        imageDetails.src=entry.nativeURL;
                        // Here I get the corect data that I want to send to the controller
                        window.alert('imageDetails='+ JSON.stringify(imageDetails));                          
                      }

                      function fail(error) {
                        window.alert("Fail: " + error.code);
                      }

                      function makeid() { 
                        var text = '';
                        var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

                        for (var i=0; i < 5; i++) {
                          text += possible.charAt(Math.floor(Math.random() * possible.length));
                        }
                        return text;
                      }                      
        }, function(err) {
          window.alert(err);
        });        
      return imageDetails;

  }; // end addImage();
    });

CONTROLLER:

    'use strict';
    angular.module('MyDemoApp.controllers')

    .controller('SignupCtrl', function ($scope, ImageService) {

        $scope.user = {};
        $scope.addNewImage  = function (method){

            /* V1 WHAT I'VE TRIED */
                var test = ImageService.addImage(method)
                $scope.user.image = test;    
                window.alert('Final '+JSON.stringify(test));


            /* V1 WHAT I'VE TRIED */
                /*
                ImageService.addImage(method).then(function(data){
                    window.alert('Final'+JSON.stringify(data));
                    $scope.user.image = data.src;
                },function(err){
                    window.alert('add image error: === ' + JSON.stringify(err));
                });  
            */    
        }
    });

What I want is to set the value what I get in onCopySuccess (from service) on $scope.user.image (but only when service finish his work ...to get the correct data).

But all the time $scope.user.image will be empty and I will see, first, the window.alert('Final '+JSON.stringify(test)); and only then the alert from onCopySuccess (window.alert('success');)

I am using a service because I will need the add picture functionality for users, photo gallery and other app sections

I really appreciate any help. Thanks

$cordovaCamera.getPicture returns a promise, therefore it is asynchronous. You are returning a value you don't have yet. Your addImage function should return a promise and your controller should use the result of that promise.

https://docs.angularjs.org/api/ng/service/$q

Basically:

1) create a new deferred using $q.defer() object in addImage()

2) return deferred.promise at the end of addImage()

3) call deferred.resolve(imageDetails) in onCopySuccess

4) use it the following way:

ImageService.addImage(method).then(function(data){
  window.alert('Final'+JSON.stringify(data));
  $scope.user.image = data.src;
});

You should also handle errors (see angular docs for more info).

You have to return the data from the promise and return the promise from the service, then use it with .then() as in your commented-out code.

Service Code:

this.addImage = function (method){
    var imageDetails ={'name':'', 'src':''};
    ...
    return $cordovaCamera.getPicture(options).then(function(imageData) {
        ...
        return imageDetails;                     
    }, function(err) {
      window.alert(err);
    });
};

Controller Code:

ImageService.addImage(method).then(function (imageDetails){
    window.alert('Final'+JSON.stringify(imageDetails));
    $scope.user.image = imageDetails.src;
},function (err){
    window.alert('add image error: === ' + JSON.stringify(err));
});