简体   繁体   中英

How to use AngularJS promises with Cordova Camera correctly?

I am having a series of functions that need to be executed in a synchronous order. One of these function is to get a picture using the Cordova Camera library from the phone of the user. Another function takes the image source and draws it in the DOM.

I work with Angular promises and the $q library to handle the synchronous execution. However, it seems that it somehow results in not updating the DOM when the functions are executed in order, even though the image was captured successfully and I have the url (ImageData).

To test, I added a function that draws the image on the DOM using the url that has been saved when the image has been captured from the phone. This does work. So there must be a problem with the use of my Angular Promises and handling of it.

How can I resolve this?

controllers ($q injected)

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;

}

// execution cycle (in controller)

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

services ($cordovaCamera injected)

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

Is this the problem:

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

An onload handler needs to be a function. You are executing ctx.drawImage() immediately.

Try this:

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


FYI, the stuff you are doing with $q.defer() in sDrawImage (and elsewhere) is unnecessary. If you want to pass imageSrc on to the next step, you can just do this:

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

Any time you think of using $q.defer() , you should ask yourself "do I really need this?". 99.5% of the time, the answer should be "No."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM