У меня проблема с восстановлением URL-адреса после putString в хранилище. Я хочу сохранить фотографию, сделанную пользователем, и сохранить некоторые метаданные, URL-адрес фотографии и идентификатор пользователя в моем bdd.
Мое приложение не выдает ошибку, изображение загружается в мое хранилище firebase, а моя модель сохраняется в fireBase, но восстановленный URL-адрес равен нулю.
Смотрите мой код: Моя служба хранения
import * as firebase from 'firebase';
export class StorageService {
public static readonly CHILD_PATH = '/photos/';
public static readonly FORMAT = '.jpg';
public static readonly BASE = 'base64';
public static readonly CONTENT_TYPE = 'image/jpg';
constructor() {}
savePhoto(data: string): string{
let fileName = new Date().getTime().toString();
let downloadUrl: string = null;
let baseReference = firebase.storage().ref();
let childReference = baseReference.child(StorageService.CHILD_PATH + fileName + StorageService.FORMAT);
let task = childReference.putString(data, StorageService.BASE, {contentType:StorageService.CONTENT_TYPE});
task
.then(snapshot => snapshot.ref.getDownloadURL())
.then(url => downloadUrl = url)
.catch(
(error) => {
throw new Error(error.toString());
}
);
return downloadUrl;
}
}
Мои изображения
import {Injectable} from "@angular/core";
import {Picture} from "../models/Picture.model";
import {Subject} from "rxjs";
import * as firebase from 'firebase';
import DataSnapshot = firebase.database.DataSnapshot;
import {Platform} from "ionic-angular";
import {StorageService} from "./Storage.service";
@Injectable()
export class PictureService {
pictures: Picture[] = [];
picturesSubject = new Subject<Picture[]>();
constructor(private platform: Platform,
private storageService: StorageService){
this.platform.ready().then(() => {
this.getPictures();
});
}
emitPictures() {
this.picturesSubject.next(this.pictures);
}
savePictures() {
firebase.database().ref('/pictures').set(this.pictures);
}
getPictures() {
firebase.database().ref('/pictures').on('value', (data: DataSnapshot) => {
this.pictures = data.val() ? data.val() : [];
this.emitPictures();
});
}
createNewPicture(newPicture: Picture, data: string) {
try{
let url = this.storageService.savePhoto(data);
newPicture.setUrl(url);
this.pictures.push(newPicture);
this.savePictures();
this.emitPictures();
} catch (e) {
throw new Error(e.toString());
}
}
}
Спасибо за вашу помощь.
Да, Дуг Стивенсон, это асинхронный метод, но .then должен выполняться после обработки, нет?
Да, и он также возвращает обещание с асинхронным разрешением. Каждый раз, когда вы получаете обещание, он отслеживает некоторую асинхронную работу. Правила не меняются.
Хорошо, прочитав статью, я понял свою ошибку. Я изменил свой код, чтобы вернуть обещание в моей службе хранилища, а не URL-адрес, который не готов. Это решит мою проблему. Спасибо, Дуг Стивенсон, за уделенное время.

putStringявляется асинхронным и возвращает обещание, и все следующие блокиthenтакже являются асинхронными. Это означает, что вы возвращаете URL-адрес загрузки до того, как вся работа будет завершена. Вам придется научиться правильно работать с обещаниями, возможно, используя async / await.