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

时间:2015-03-12 20:14:40

标签: angularjs cordova ionic-framework angularjs-service angularjs-controller

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

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

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

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

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

我非常感谢任何帮助。 感谢

2 个答案:

答案 0 :(得分:0)

$cordovaCamera.getPicture返回一个promise,因此它是异步的。您将返回一个您还没有的值。你的addImage函数应该返回一个promise,你的控制器应该使用该promise的结果。

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

基本上:

1)使用deferred

中的$q.defer()对象创建新的addImage()

2)在deferred.promise

的末尾返回addImage()

3)在deferred.resolve(imageDetails)

中致电onCopySuccess

4)以下列方式使用它:

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

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

答案 1 :(得分:0)

您必须从承诺中返回数据并从服务中返回承诺,然后将其与.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));
});