angular - การเรียกฟังก์ชันแบบอะซิงโครนัสไม่ให้ผลลัพธ์ใด ๆ กับฟังก์ชันหลักที่เรียก
ฉันกำลังพยายามดึงค่าของฟิลด์เอกสารโดยใช้ documentID ฉันได้แก้ไขส่วนการเรียกฐานข้อมูลแล้ว แต่ฉันไม่สามารถส่งข้อมูลกลับขึ้นไปได้ เหมือนกับว่าฟังก์ชัน this.userDbService.getVendorNameFromUserId ด้านล่างนี้ไม่ได้ถูกเรียกใช้งานเลย
นี่คือฟังก์ชันหลัก:
async getVendorName() {
let name;
//blindtiger not going here.
//calling to 'private userDbService: UserDbService'
name = await this.userDbService.getVendorNameFromUserId('2OD1yTnMrecMgqljvHFHDjug1VT2');
console.log(name);
return name.toString();}
และนี่คือฟังก์ชัน getVendorNameFromUserId(''):
async getVendorNameFromUserId(id: string): Promise<string> {
let vendorName = '';
const userCollectionRef = await doc(this.store, 'clients/' + id);
await docData(userCollectionRef, {idField: 'id'}).forEach(el => {
//correctly is 'blindtiger' from db call.
console.log(el['user'].companyName.toString())
return el['user'].companyName.toString();
});
//parent function doesn't yield any results - as if this is not called.
// It should yield 'blindtiger' here.
return 'NOT FOUND';
}
getVendorName() ถูกเรียกใช้งานภายในตัวสร้างของไฟล์ TypeScript ค่าผลลัพธ์ของฟังก์ชันนี้ถูกนำไปใช้เพื่อดึงสินค้าทั้งหมดสำหรับชื่อผู้ขายนั้น
constructor(private shopifyService: ShopifyService, private userDbService: UserDbService, private modalService: NgbModal, private userAuthService: UserAuthService, private itemDb: ItemDbService) {
let vendorName: string;
const name = this.getVendorName();
console.log(name);
this.getAllProducts(name).then(result => {
console.log(result);
this.itemsToSell = result;
});
}`
ฉันมีความรู้สึกว่าฉันกำลังพลาดบางสิ่งที่เกี่ยวกับ async - แต่ฉันยินดีรับคำแนะนำใด ๆ ว่าทำไมค่าของ 'blindtiger' ถึงไม่ถูกส่งขึ้นไปตามโซ่เลย
ฉันได้ลองเพิ่ม async await ในการเรียกฟังก์ชัน - getVendorNameFromUserId() แล้ว ถ้าฉันลบคำสั่ง await หน้าฟังก์ชัน docData() ที่นี่:
await docData(userCollectionRef, {idField: 'id'}).forEach(el => {
//correctly is 'blindtiger' from db call.
console.log(el['user'].companyName.toString())
return el['user'].companyName.toString();
});`
ฉันได้รับผลลัพธ์ 'NOT FOUND' ซึ่งบ่งชี้ว่านี่ส่งข้อมูลขึ้นไปตามลำดับชั้นได้ถูกต้อง ฉันกำลังคิดว่ามีปัญหากับฟังก์ชันนี้ที่ไม่ได้รอโดยฟังก์ชันที่เรียกใช้ซึ่งมีลักษณะดังนี้:
async getVendorName() {
let name;
//blindtiger not going here.
//calling to 'private userDbService: UserDbService'
name = await this.userDbService.getVendorNameFromUserId('2OD1yTnMrecMgqljvHFHDjug1VT2');
console.log(name);
return name.toString();
}
docData คืนค่าการสังเกตได้
const data = await docData(userCollectionRef, {idField: 'id'}).pipe(take(1)).subscribe(user => {
vendorName = user['user'].companyName;
//does not yield blind tiger
console.log({dataDone: vendorName});
})
//does yield blind tiger
console.log({dataAfter: vendorName})
return vendorName['user'].companyName
}
คำตอบ #1
ฉันสันนิษฐานว่า docData() จะคืนค่าเป็นอาเรย์ซึ่งคุณต้องการเพียงค่าตัวแรก เนื่องจากลายเซ็นของเมธอดอ่านว่า getVendorNameFromUserId และคุณส่ง id เพียงค่าเดียว ดังนั้นโค้ดของคุณอาจมีลักษณะดังนี้:
async getVendorName() {
const name = await this.userDbService.getVendorNameFromUserId('2OD1yTnMrecMgqljvHFHDjug1VT2');
console.log('name', name);
return name;
}
async getVendorNameFromUserId(id: string): Promise<string> {
const userCollectionRef = await doc(this.store, 'clients/' + id);
console.log('userCollectionRef', userCollectionRef);
const resultArray = await firstValueFrom(docData(userCollectionRef, {idField: 'id'}));
console.log('resultArray', resultArray);
// Get the first element from array, given the array has at least one element
const vendorName = resultArray?.map(el => el.user.companyName.toString())?.[0];
return vendorName ?? 'NOT FOUND';
}
โปรดทราบ: คุณไม่จำเป็นต้องเขียน toString() ใน getVendorName() เนื่องจาก getVendorNameFromUserId() ได้คืนค่า promise ประเภท string แล้ว
คำตอบ #2
คุณมีการคืนค่าใน foreach ของคุณ: มันจะคืนค่าผลลัพธ์สำหรับ foreach ไม่ใช่ getVendorNameFromUserId ใช้ forof ธรรมดาแทน
async getVendorNameFromUserId(id: string): Promise<string> {
let vendorName = '';
const userCollectionRef = await doc(this.store, 'clients/' + id);
const data = await docData(userCollectionRef, {idField: 'id'});
for (const el of data) {
//it will return the first found. Don't you need condition to search from criterias?
//correctly is 'blindtiger' from db call.
console.log(el['user'].companyName.toString())
return el['user'].companyName.toString();
}
//parent function doesn't yield any results - as if this is not called.
// It should yield 'blindtiger' here.
return 'NOT FOUND';
}
- โบนัส : หลีกเลี่ยงการใช้ async ในตัวสร้าง สำหรับการเริ่มต้นแบบ async คุณสามารถใช้ APP_INITIALIZER ใน Angular ได้
