Save function value base64 in array?

1

I am working on an application in ionic framework and I need to send the following object by $http by post method.

$scope.project = {
      name: '',
      description:'',
      location: '',
      imgs: {},
      video: ''
  };

I have no problem with the name, description or location. The problem arises when wanting to store images in base64 within "imgs".

To be able to convert the images I use the following function:

function toDataUrl(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';
    xhr.onload = function() {
      var reader = new FileReader();
      reader.onloadend = function() {
        callback(reader.result);
      };
      reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.send();
  }

And this is how I call her:

allImages is an array with the paths of the images.

if($scope.allImages.length>0){
   for (var i = 0; i < $scope.allImages.length; i++) {
        toDataUrl($scope.allImages[i], function(base64File){
            alert(base64File);
            //Guardar valor en base64 en el objeto.
            $scope.project.imgs[i]=base64File;
        });
   }
}

imprimeObjeto($scope.project.imgs);

But when executing my code what happens is that, first the impression that I do until the end is shown: imprimeObjeto($scope.project.imgs); and it shows me everything empty, then it shows the alert with the correct code in base64 converted to the 'toDataUrl' function, I can see all the image code in base64 , but this value is not saved in the array, or only saves the value of the last selected image.

What I need is to save the base64 code inside the imgs object something like this:

$scope.project = {
      name: '',
      description:'',
      location: '',
      imgs: {
              0 : 'codigoBase64blabla.....',
              1 : 'codigoBase64blaasdq....',
              2 : 'codigoBase64blablalbla.',
              3 : 'codigoBase64blabla.....',
              4 : 'codigoBase64blabla.....'
            },
      video: ''
  };

But for some reason, the code in base64 is generated but not stored in the array.

I think it takes too long to convert the images and that makes it skip lines of code. Is there a way to first save the images in base64 inside the object and not print the end first?

Even I am very new in angular, can this be done with promises?

    
asked by edgargrs 20.08.2016 в 08:44
source

1 answer

1

I think you're using the formula to convert images to base64 which can be found in this StackOverflow question

link

This uses XMLHttpRequest since it is a general-purpose formula. In your case you are using angular and you must use the service $http that is from a level of abstraction higher than using the javascript API directly, because if for example you have an interceptor enabled, it will stop working in that particular case.

Answering your question

  

Is there a way to first save the base64 images inside the object and not print the end first? I'm still very new in angular, can you do this with promises?

I think you're on the right path. The function toDataUrl contains asynchronous code so if you try to print it at the moment it will not give you any results.

To fix this you must return a promise but here you must use what is known as

Explicit construction

// Ya no es necesario el parámetro callback
function toDataUrl(url) {
    // Creas un nuevo objeto deferred
    var defer = $q.defer();
    // Usas el servicio $http para la petición
    $http.get(url, {responseType:'blob'}).then(function (response) {
        var reader = new FileReader();
        reader.onloadend = function() {
            // resuelves la promesa con los datos leídos
            defer.resolve(reader.result);
        };
        reader.readAsDataURL(response.data);
    }).catch(function(err) {
        // Rechazas la promesa en caso de error
        defer.reject(err);
    });

    // Retornas la promesa que acabas de crear
    return defer.promise;
}

And then combine using $ q.all

var promesas = [];
if($scope.allImages.length > 0) {
   for (var i = 0; i < $scope.allImages.length; i++) {
        promesas.push(toDataUrl($scope.allImages[i]));
   }
}

$q.all(promesas).then(function(imagenes) {
    for (var i = 0; i < imagenes.length; i++) {
        $scope.project.imgs[i] = imagenes[i];
    }
    imprimeObjeto($scope.project.imgs);       
});
    
answered by 22.08.2016 / 16:53
source