ค้นหาเว็บไซต์

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 ได้