在使用FireStore和angularfire2的Angular 5中,通过控制器从服务获取文档时处理错误的正确方法是什么?
服务:
Sub Compress(filename As String, zippedFile As String)
If IO.File.Exists(zippedFile) Then IO.File.Delete(zippedFile)
If IO.File.Exists(filename) Then
Using archive As ZipArchive = Open(zippedFile, ZipArchiveMode.Create)
archive.CreateEntryFromFile(filename, Path.GetFileName(filename), CompressionLevel.Fastest)
End Using
End If
End Sub
控制器:
getInviteById( inviteId: string ): Promise<any> {
// get requested invite from firestore
var inviteDocument = this.afs.collection( 'invites' ).doc( inviteId );
let invite = inviteDocument.ref.get().then( doc => {
// if document exists
if (doc.exists) {
// return id and data
const id = doc.id;
var data = doc.data() as any;
return { id, ...data };
// if document does not exist
} else {
console.log("Error: No such document!");
// WHAT DO I NEED TO RETURN HERE???
}
// if other error
}).catch(function(error) {
console.log("Error: Getting document:", error);
// WHAT DO I NEED TO RETURN HERE???
});
// return invite
return invite;
};
如果FireStore中存在具有invite-id的文档,则一切正常。但是,如果FireStore中没有邀请ID的文档,则该服务将记录“错误:没有此类文档!” (正如预期的那样),但该组件不会进入自己的this.inviteService.getInviteById( inviteId )
.then( resolve => {
this.invite = resolve;
})
.catch( err => {
// THIS NEVER GETS CALLED !
console.log("INVITE-COMPONENT: Cannot get invite for this id." );
});
案例。
如何处理组件中的“无此类文档”错误,以便我可以相应地修改我的用户界面?
答案 0 :(得分:1)
您可以返回被拒绝的承诺,但throw
更简单。
所以,直截了当地,你可以写:
// (1) ILLUSTRATIVE - NOT YET THE FULL SOLUTION
getInviteById(inviteId: string): Promise<any> {
var inviteDocument = this.afs.collection('invites').doc(inviteId);
return inviteDocument.ref.get()
.then(doc => {
if (doc.exists) { // if document exists ...
const id = doc.id;
var data = doc.data() as any;
return {id, ...data}; // ... return id and data.
} else { // if document does not exist ...
throw new error('No such document!'); // ... throw an Error.
}
})
.catch(error => {
throw new Error('Error: Getting document:'); // throw an Error
});
};
但是,内部throw
会立即被外部.catch()
和“没有这样的文件”抓住!错误消息将丢失,以支持'错误:获取文档:'。
通过如下调整整体模式可以避免这种损失:
// (2) ILLUSTRATIVE - NOT YET THE FULL SOLUTION
getInviteById(inviteId: string): Promise<any> {
var inviteDocument = this.afs.collection('invites').doc(inviteId);
return inviteDocument.ref.get()
.catch(error => { // .catch() error arising from inviteDocument.ref.get()
throw new Error('Error: Getting document:');
})
.then(doc => {
if (doc.exists) {
const id = doc.id;
var data = doc.data() as any;
return {id, ...data};
} else {
throw new error('No such document!'); // can now be caught only by getInviteById's caller
}
});
};
但是,即使这还不正确,因为存在以下可能性:
this.afs.collection('invites').doc(inviteId)
可能会返回null
,在这种情况下应该抛出错误。 this.afs.collection('invites').doc(inviteId)
或inviteDocument.ref.get()
可能会同步 。在任何一种情况下,调用者都有权期望一个promise-returns函数总是抛出异步,无论错误发生的方式/位置如何。
可以通过确保从promise链内执行var inviteDocument = this.afs.collection('invites').doc(inviteId);
和inviteDocument.ref.get()
来解决该工件,并正确处理null
案例,如下所示:
// (3) SOLUTION
getInviteById(inviteId: string): Promise<any> {
return Promise.resolve() // neutral starter promise
.then(() => {
var inviteDocument = this.afs.collection('invites').doc(inviteId); // now executed inside promise chain
if(inviteDocument) {
return inviteDocument.ref.get(); // now executed inside promise chain.
} else {
throw new Error(); // no point setting an error message here as it will be overridden below.
}
})
.catch(error => {
throw new Error('Error: Getting document:');
})
.then(doc => {
if (doc.exists) {
const id = doc.id;
var data = doc.data() as any;
return {id, ...data};
} else {
throw new error('No such document!');
}
});
};
调用者(您的控制器)将捕获并记录getInviteById()
:
this.inviteService.getInviteById(inviteId)
.then(result => { // better not to name the variable `resolve`
this.invite = result;
})
.catch(err => {
console.log("INVITE-COMPONENT: Cannot get invite for this id: " + error.message);
});
备注强>
console.log()
在getInviteById()
内是不必要的(调试时除外)。来电者.catch()
将执行所有必要的记录。
醇>