我在我的 Vue 项目中使用 Firestore,我正在开发一项允许用户上传图片的功能,但是我面临以下问题:
我有一个“newMarker”占位符对象,用户可以在其中填写信息,一旦用户确认输入,该对象就会保存到数据库中。当用户确认我想要的输入时:
但是我不知道如何让代码等待上传状态完成后立即运行的回调函数(在uploadIMG函数中,'uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED',最后一个回调函数)并返回一个带有url的promise。不管我做什么,这个回调函数最后执行。
当用户确认输入时,会执行 saveNewMarker() 并运行以下代码:
我的代码:
async saveNewMarker() {
await this.uploadImg();
console.log('Image upload finished! Pushing new marker to db')
await db.collection(this.user.email).add({
position: this.newMarker.position,
type: this.newMarker.type,
location: this.newMarker.location,
imgURL: this.newMarker.imgURL
})
.then((marker) => {
console.log('marker added to database')
this.newMarker.id = marker.id
})
},
async uploadImg(){
console.log('Uploading image ...')
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child('user-uploads/images/' + this.file.name).put(this.name)
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
},
(error) => {
console.log(error)
},
async () => {
const imgURL = await uploadTask.snapshot.ref.getDownloadURL()
console.log('uploaded image: ' + imgURL)
this.newMarker.imgURL = imgURL
}
);
},
输出:
Uploading image ...
Upload is NaN% done
Image upload finished! Pushing new marker to db
marker added to database
uploaded image: https://firebasestorage.googleapis.com/v0/b/....
预期输出:
Uploading image ...
Upload is NaN% done
uploaded image: https://firebasestorage.googleapis.com/v0/b/....
Image upload finished! Pushing new marker to db
marker added to database
答案 0 :(得分:1)
您必须将代码封装在 uploadImg
中,并在图片上传完成后解决它。将 uploadImg
重构为如下所示的内容应该可以:
async uploadImg() {
return new Promise((resolve, reject) => {
console.log("Uploading image ...");
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child("user-uploads/images/" + this.file.name).put(this.name);
uploadTask.on(
firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is " + progress + "% done");
},
(error) => {
console.log(error);
reject(error);
},
async () => {
const imgURL = await uploadTask.snapshot.ref.getDownloadURL();
console.log("uploaded image: " + imgURL);
this.newMarker.imgURL = imgURL;
resolve();
}
);
});
},
答案 1 :(得分:1)
这不是 async/await 的用途,我建议改用 Promises,就像这样:
function saveNewMarker() {
// Call uploadImg as a Promise and wait for the result
this.uploadImg()
.then((imgURL) => {
console.log('Image upload finished! Pushing new marker to db');
db.collection(this.user.email).add({
position: this.newMarker.position,
type: this.newMarker.type,
location: this.newMarker.location,
imgURL: this.newMarker.imgURL
})
.then((marker) => {
console.log('marker added to database');
this.newMarker.id = marker.id;
})
}).catch((error) => {
//Do something
});
};
function uploadImg() {
// Return a promise that will either resolve or emit an error
return new Promise((resolve, reject) => {
console.log('Uploading image ...');
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child('user-uploads/images/' + this.file.name).put(this.name);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log('Upload is ' + progress + '% done');
},
(error) => {
console.log(error);
// An error occurred so inform the caller
reject(error);
},
async () => {
const imgURL = await uploadTask.snapshot.ref.getDownloadURL();
console.log('uploaded image: ' + imgURL);
this.newMarker.imgURL = imgURL;
// We 'awaited' the imgURL, now resolve this Promise
resolve(imgURL);
}
);
});
};
并记住您的分号以避免意外行为或错误。