Angularjs 无法从控制器中的服务获取正确的数据

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

我尝试使用 Ionic/Angular/Cordova 构建一个移动应用程序,但我遇到了一些服务问题 :) 我的代码如下所示:

服务:

    '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();
    });

控制器:

    '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));
                });  
            */    
        }
    });

我想要的是设置我在 $scope.user.image 上的 onCopySuccess(从服务)中获得的值(但只有当服务完成他的工作时......才能获得正确的数据)。

但是 $scope.user.image 一直都是空的,我首先会看到 window.alert('Final '+JSON.stringify(test));然后只有来自 onCopySuccess 的警报 (window.alert('success');)

我正在使用一项服务,因为我需要为用户、照片库和其他应用部分添加图片功能

非常感谢任何帮助。 谢谢

$cordovaCamera.getPicture return是一个承诺,因此它是异步的。您正在 return 获得一个您还没有的价值。您的 addImage 函数应该 return 一个承诺,您的控制器应该使用该承诺的结果。

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

基本上:

1) 使用 addImage()

中的 $q.defer() 对象创建一个新的 deferred

2) return deferred.promise addImage()

结尾

3) 在 onCopySuccess

中调用 deferred.resolve(imageDetails)

4) 按以下方式使用:

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

您还应该处理错误(有关详细信息,请参阅 angular 文档)。

您必须 return 来自 promise 的数据和 return 来自服务的 promise,然后将其与 .then() 一起使用,就像您注释掉的代码中那样。

服务代码:

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

控制器代码:

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));
});