如何正确使用AngularJS与Cordova相机的承诺?

时间:2015-01-27 09:56:37

标签: javascript angularjs cordova asynchronous angular-promise

我有一系列需要以同步顺序执行的功能。其中一个功能是使用用户手机上的Cordova Camera库获取图片。另一个函数接受图像源并将其绘制在DOM中。

我使用Angular promises和$ q库来处理同步执行。但是,它似乎以某种方式导致在按顺序执行函数时不更新DOM,即使图像已成功捕获并且我有url(ImageData)。

为了测试,我添加了一个函数,该函数使用从手机捕获图像时保存的URL在DOM上绘制图像。这确实有效。因此,使用我的Angular Promise并处理它一定存在问题。

我该如何解决这个问题?

控制器($ q注入)

var sGetImage = function() {

    var imageSrcOutput = "";
    $scope.imageDataSrc = null;

    try {

        imageSrcOutput = CloakService.getImageData()
            .then(function(imageData) {

                //$scope.imageData = imageData;
                $scope.imageDataSrc = "data:image/jpeg;base64," + imageData;
                //$scope.imgURI = $scope.imageDataSrc;

                return "data:image/jpeg;base64," + imageData;

            });

        // catch any errors with a struddle image
    } catch (error) {

        window.alert("No Image Picked. Drawing Struddle");
        imageSrcOutput = "img/struddle.jpg";
        $scope.imageDataSrc = imageSrcOutput;
    }

    return imageSrcOutput;

}

var sDrawImage = function(imageSrc) {

    var deferred = $q.defer();
    deferred.resolve(imageSrc)

    window.alert("drawing image now with: " + imageSrc)
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    var img = new Image();
    img.src = imageSrc;
    img.onload = ctx.drawImage(img, 0, 0);

    return deferred.promise;

}

//执行周期(在控制器中)

  sInit() // works fine
  .then( sGetImage ) // image loaded in imageSrcOutput and $scope.imageDataSrc succesfully
  .then( sDrawImage ) // here is the problem, it does not draw the images (tried both imageSrcOutput and $scope.imageDataSrc)
  .then( sAddBanner )
  .catch(function(error) {
      window.alert("Catch Error: " + error)
  })

服务($ cordovaCamera注入)

var getImageData = function() {

    var deferred = $q.defer();
    var options = getOptions('CAMERA');

    var imageDataOutput = $cordovaCamera.getPicture(options).then(function(imageData) {

        // window.alert(imageData)
        deferred.resolve(imageData)
        return imageData; //todo:check

    }, function(error) {

        deferred.reject(error)
        window.alert(error)

    });

    function getOptions(source) {
        var options = {
            quality: 75,
            destinationType: Camera.DestinationType.DATA_URL,
            sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
            allowEdit: true,
            encodingType: Camera.EncodingType.JPEG,
            targetWidth: 300,
            targetHeight: 300,
            popoverOptions: CameraPopoverOptions,
            saveToPhotoAlbum: true
        };
        return options;
    }

    return deferred.promise;
    //return imageDataOutput;
}

app.js

'use strict';
angular.module('myApp', [
    'ionic',
    'myApp.config',
    'myApp.controllers',
    'myApp.decorators',
    'myApp.directives',
    'myApp.filters',
    'myApp.routes',
    'myApp.services', 
    'angular-loading-bar',
    'ngCordova' // the library to handle the picture
  ])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if(window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

1 个答案:

答案 0 :(得分:1)

这是问题所在:

img.onload=ctx.drawImage(img, 0, 0);

onload处理程序需要是一个函数。您正在立即执行ctx.drawImage()

试试这个:

img.onload = function () { ctx.drawImage(img, 0, 0); };


仅供参考,您在$q.defer()(以及其他地方)使用sDrawImage所做的事情是不必要的。如果您想将imageSrc传递给下一步,您可以这样做:

var sDrawImage = function(imageSrc) {
    window.alert("drawing image now with: " + imageSrc)
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    var img = new Image();
    img.src = imageSrc;

    return $q(function (resolve) {
        img.onload = function () { 
            ctx.drawImage(img, 0, 0); 
            resolve(imageSrc);
        };
    });
};

每当你想到使用$q.defer()时,你应该问自己“我真的需要这个吗?”。 99.5%的时间,答案应该是“不”。