我试图从相机或图库上传图像。我写了服务中的所有代码。控制器必须从相机或图库中接收完整的URL,以便在幻灯片框中显示,但现在没有任何内容。
一切正常,但我无法将图像的网址发送回控制器。我认为错误是因为我试图在函数" obtenerImagen"之前返回值。执行。
我正在尝试实施回调,但我认为我没有正确实施。
我想用图片的网址返回的变量是 urlImagen
这是我调用服务的控制器:
//generar el popup para seleccionar el origen de la imagen: cámara o galería
function seleccionarImagen() {
cambiarImagenesService.seleccionarImagen()
.then(reemplazarImagen);
}
服务:
(function() {
'use strict';
angular
.module('example.cambiarimagenes')
.factory('cambiarImagenesService', cambiarImagenesService);
cambiarImagenesService.$inject = ['remoteDataService','$q', '$ionicPopup','$cordovaCamera', '$cordovaFile', '$cordovaFileTransfer', '$cordovaDevice', '$rootScope'];
/* @ngInject */
function cambiarImagenesService(remoteDataService,$q, $ionicPopup, $cordovaCamera, $cordovaFile, $cordovaFileTransfer, $cordovaDevice, $rootScope){
var dias = [];
var mensaje = '';
var image = null;
var urlImagen = '';
var service = {
obtenerHorariosComplejo: obtenerHorariosComplejo,
seleccionarImagen: seleccionarImagen
};
return service;
//cargar una nueva imagen
function seleccionarImagen() {
var popup = seleccionarImagenPopup();
return $ionicPopup.show(popup).then(function(result) {
if (result == -1) {
return false;
}
return urlImagen;
});
}
function obtenerImagen(sourceType, callback){
var options = {
callback: callback,
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function(imagePath) {
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//Create a new name for the photo
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
// If you are trying to load image from the gallery on Android we need special treatment!
if ($cordovaDevice.getPlatform() == 'Android' && sourceType === Camera.PictureSourceType.PHOTOLIBRARY) {
window.FilePath.resolveNativePath(imagePath, function(entry) {
window.resolveLocalFileSystemURL(entry, success, fail);
function fail(e) {
console.error('Error: ', e);
}
function success(fileEntry) {
var namePath = fileEntry.nativeURL.substr(0, fileEntry.nativeURL.lastIndexOf('/') + 1);
// Only copy because of access rights
$cordovaFile.copyFile(namePath, fileEntry.name, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
urlImagen = image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
};
}
);
} else {
var namePath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
// Move the file to permanent storage
$cordovaFile.moveFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
urlImagen = image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
}
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
})
}
//poopup para cargar nuevo imagen
function seleccionarImagenPopup() {
var scope = $rootScope.$new();
scope.data = {
tipo: null
};
return {
templateUrl: 'scripts/complejo/agenda/nuevo-turno.html',
title: "¿De dónde desea obtener la imagen?",
scope: scope,
buttons: [{
text: 'Cancelar',
onTap: function(e) {
scope.tipo = -1
return scope.tipo;
}
}, {
text: '<b>Cámara</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
obtenerImagen(scope.tipo, function(val){
urlImagen = val;
});
console.log("el valor de la imagen al tocar la camara es:"+image);
return urlImagen;
}
}, {
text: '<b>Galería</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.PHOTOLIBRARY;
obtenerImagen(scope.tipo, function(val){
urlImagen = val;
});
console.log("el valor de la imagen al tocar la galeria es:"+image);
return urlImagen;
}
}]
};
}
//generar error si hubo un problema
function generarError(e){
console.log("error!!!!!!:"+e);
if (e.message) {
return $q.reject(e.message);
}
return $q.reject('Ups! Hubo un problema al conectarse al servidor.');
}
}
})();
感谢您的帮助!
// 修改 //
这是我的服务:
(function() {
'use strict';
angular
.module('example.cambiarimagenes')
.factory('cambiarImagenesService', cambiarImagenesService);
cambiarImagenesService.$inject = ['remoteDataService','$q', '$ionicPopup','$cordovaCamera', '$cordovaFile', '$cordovaFileTransfer', '$cordovaDevice', '$rootScope'];
/* @ngInject */
function cambiarImagenesService(remoteDataService,$q, $ionicPopup,$cordovaCamera, $cordovaFile, $cordovaFileTransfer, $cordovaDevice, $rootScope){
var dias = [];
var mensaje = '';
var image = null;
var urlImagen = '';
var service = {
obtenerHorariosComplejo: obtenerHorariosComplejo,
seleccionarImagen: seleccionarImagen
};
return service;
//cargar una nueva imagen
function seleccionarImagen() {
var popup = seleccionarImagenPopup();
return $ionicPopup.show(popup).then(function(result) {
if (result == -1) {
return false;
}
return urlImagen;
});
}
function obtenerImagen(sourceType){
var options = {
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
return $cordovaCamera.getPicture(options).then(function(imagePath) {
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//Create a new name for the photo
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
// If you are trying to load image from the gallery on Android we need special treatment!
if ($cordovaDevice.getPlatform() == 'Android' && sourceType === Camera.PictureSourceType.PHOTOLIBRARY) {
window.FilePath.resolveNativePath(imagePath, function(entry) {
window.resolveLocalFileSystemURL(entry, success, fail);
function fail(e) {
console.error('Error: ', e);
}
function success(fileEntry) {
var namePath = fileEntry.nativeURL.substr(0, fileEntry.nativeURL.lastIndexOf('/') + 1);
// Only copy because of access rights
$cordovaFile.copyFile(namePath, fileEntry.name, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
return image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
};
}
);
} else {
var namePath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
// Move the file to permanent storage
$cordovaFile.moveFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
return image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
}
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
})
}
//poopup para cargar nuevo imagen
function seleccionarImagenPopup() {
var scope = $rootScope.$new();
scope.data = {
tipo: null
};
return {
templateUrl: 'scripts/complejo/agenda/nuevo-turno.html',
title: "¿De dónde desea obtener la imagen?",
scope: scope,
buttons: [{
text: 'Cancelar',
onTap: function(e) {
scope.tipo = -1
return scope.tipo;
}
}, {
text: '<b>Cámara</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
var promise = obtenerImagen(scope.tipo)
.then(function(val){
// asignamos el valor asincrónico
urlImagen = val;
// retornamos el valor a la cadena
return val;
});
// retornamos la promesa de manera síncrona
return promise;
}
}, {
text: '<b>Galería</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.PHOTOLIBRARY;
var promise = obtenerImagen(scope.tipo)
.then(function(val){
// asignamos el valor asincrónico
urlImagen = val;
// retornamos el valor a la cadena
return val;
});
// retornamos la promesa de manera síncrona
return promise;
}
}]
};
}
//generar error si hubo un problema
function generarError(e){
console.log("error!!!!!!:"+e);
if (e.message) {
return $q.reject(e.message);
}
return $q.reject('Ups! Hubo un problema al conectarse al servidor.');
}
}
})();
答案 0 :(得分:0)
你非常接近你想要的东西。您只需调用传递给callback
函数的obtenerImagen
。
在你的成功功能中:
function success(fileEntry) {
urlImagen = image;
callback(urlImagen);
}
您的回调函数已将url
作为参数。
答案 1 :(得分:0)
问题是回调函数是以异步方式执行的。
//ERRONEOUS
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
obtenerImagen(scope.tipo, function(val){
//ASYNCHRONOUSLY ASSIGNED
urlImagen = val;
});
console.log("el valor de la imagen al tocar la camara es:"+image);
//SYNCHRONOUSLY RETURNED
return urlImagen;
}
在分配值之前返回值。后续代码在定义值之前执行。
obtenerImagen
函数需要重构才能返回一个promise,并且需要返回promise。
//GOOD
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
var promise = obtenerImagenPromise(scope.tip)
.then(function(val){
//ASYNCHRONOUSLY ASSIGNED
urlImagen = val;
//return value to chain
return val;
});
//SYNCHRONOUSLY RETURN PENDING PROMISE
return promise;
}
通过返回一个promise,后续代码可以使用promise的.then
方法来延迟执行,直到定义了值。
因为调用promise的.then
方法会返回一个新的派生promise,所以很容易创建一个promise链。可以创建任意长度的链,并且由于承诺可以通过另一个承诺来解决(这将进一步推迟其解决方案),因此可以在任何时候暂停/推迟对承诺的解决连锁,链条。这使得实现强大的API成为可能。
- AngularJS $q Service API Reference - Chaining Promises
另见SO: Why are Callbacks from Promise .then
Methods an Anti-Pattern
我需要做什么改变&#34; obtenerImagenPromise&#34;正确地返回承诺?因为现在我有以下错误&#34; TypeError:无法读取属性&#39;然后&#39;未定义&#34;我想我需要在函数中返回图像&#34; obtenerImagenPromise&#34;
首先从$cordovaCamera.getPicture
返回派生的承诺:
//function obtenerImagen(sourceType, callback){
function obtenerImagenPromise(sourceType){
var options = {
//callback: callback,
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
//$cordovaCamera.getPicture(options).then(function(imagePath) {
return $cordovaCamera.getPicture(options).then(function(imagePath) {
//^^^^^^ ---- return derived promise
// Grab the file name of the photo in the temporary directory
.then
方法始终返回新的派生承诺。该承诺需要返回到父函数。还要确保.then
方法中的函数返回值或承诺。未能返回某些内容将导致承诺解析为undefined
。
我设置了返回但总是控制器收到
undefined
调试提示:放置console.log
语句以查看中间值:
//$cordovaCamera.getPicture(options).then(function(imagePath) {
return $cordovaCamera.getPicture(options)
//^^^^^^ ---- return derived promise
.then(
function(imagePath) {
//ADD console.log to see intermediate data
console.log("getPicture success handler called");
console.log("imagePath= "+imagePath);
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//...
//Always return something
return "something";
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
//throw to chain error
throw "error en el serivicio o cancelacion:"+err
}
);
};
还要确保.then
方法中的函数返回值或承诺。未能返回某些内容将导致承诺解析为undefined
。
功能编程的经验法则是 - 总是返回一些东西。
答案 2 :(得分:-1)
用此更换服务中的seleccionarImagen功能;
function seleccionarImagen() {
var deferred = $q.defer();
var popup = seleccionarImagenPopup();
$ionicPopup.show(popup).then(function(result){
if(result == -1)
deferred.reject(result);
deferred.resolve(result);
}, function(err){
deferred.reject(err);
});
return deferred.promise;
}
&#13;