如何等待值然后返回一个对象

Posted

技术标签:

【中文标题】如何等待值然后返回一个对象【英文标题】:How to wait for values then return an object 【发布时间】:2021-07-13 04:40:56 【问题描述】:

我正在将图像文件上传到服务器,并想用我的上传方法返回下载网址和上传百分比。

目前这可行,但将来,我希望能够使用相同的组件上传多张图片,并在上传表单下方显示一个表格,其中包含成功上传的文件名,以及删除它们的按钮。

我想知道是否有人可以为我指明正确的方向,只要有新上传的文件可用,就可以使用 Promise 或异步回调来完成本质上将新的 downloadURL : Observable<string>, uploadPercentage : Observable<number> 对象推送到数组。

上传方法,在upload-form component.ts中


  upload(file) 
    // this.id = Math.random().toString(36).substring(2);
    
    const folder = this.mode == 'single' ? 'titleCardImages' : 'contentImages' 


    const filePath = `$folder/$file.name`;
    const fileRef = this.afStorage.ref(filePath);
    const task = this.afStorage.upload(filePath, file)
    // observe percentage changes
    this.uploadPercent = task.percentageChanges();
    // get notified when the download URL is available
    task.snapshotChanges().pipe(
        finalize(() => this.downloadURL = fileRef.getDownloadURL() )
    )
    .subscribe()
    

editNewsComponent.html(摘录)垫子对话框

<h2 mat-dialog-title>Create, Update or delete news</h2>

<mat-dialog-content [formGroup]="form">

  <mat-form-field>
      <input matInput
              placeholder="Title"
              formControlName="title">
  </mat-form-field> <br>


  <br><label for="titleCardImage">Title Card Image:</label> <br>
  <upload-image
    mode="single"
    label="Enter a title card image">
  </upload-image>


  <!-- <button (click)="fileInput.click()">
    <span>Select</span>
    <input #fileInput type="file" (change)="upload($event)" style="display:none;" />
    
  
  </button> <br> -->


  


  <mat-form-field>
    <textarea matInput
            placeholder="a short description"
            formControlName="description"></textarea>
  </mat-form-field> <br>

  <mat-form-field>
    <textarea matInput
            placeholder="Body/Content of the news piece"
            formControlName="body"></textarea>
  </mat-form-field> <br>


  <label id="example-radio-group-label">Tags: <br></label>
  <mat-chip-list aria-label="tag selection" >
    <mat-chip>One fish</mat-chip>
    <mat-chip>Two fish</mat-chip>
    <mat-chip color="primary" selected>Primary fish</mat-chip>
    <mat-chip color="accent" selected>Accent fish</mat-chip>
  </mat-chip-list>
  
</mat-dialog-content>

<mat-dialog-actions>
    
  <button
    mat-stroked-button
    (click)="reset()"
    >
    Clear
  </button>
  <button
    mat-dialog-close
    mat-stroked-button>
    Cancle
  </button>
  <button
    (click)="save()"
    mat-raised-button>
    Save
  </button>

  <p>Form data:  form.value | json </p>

</mat-dialog-actions>

非常感谢任何帮助

【问题讨论】:

您的上传方法应该与处理该数组无关。它返回(一个承诺)下载 url 和(一个可观察的)上传百分比,这就是它的全部责任。这个方法的调用者,可能同时调用它多次的那个,应该处理把它放到数组中。现在问题到底出在哪里?请向我们展示您的方法的代码以及在该组件中使用它的尝试。 我很确定他指的是调用者 - 为什么每个人都如此直截了当并准备贬低人? 是的,我并不是说我想在 upload(file) 方法中设置这个数组,但从理论上讲,你如何从同一个函数/方法返回一个 promise 和 observable? @DIGIByte 我很确定他不是——问题是如何从上传方法本身返回这个。 我不想对框架做出假设,当你也依赖于角度方法时,打字稿太模糊了。我不认为有任何混淆,我认为没有必要将您的字面意思视为问题,只是您有一个想要解决的问题既然我们已经澄清它是 Angular,您可以查看Fireship 如何使用 Angular/fire fireship.io/lessons/angular-firebase-storage-uploads-multi 【参考方案1】:

这当然是可能的,您需要根据项目的设计进行调整

Fireship.io 有一个非常好的 Angular/Fire 解决方案 来源:https://fireship.io/lessons/angular-firebase-storage-uploads-multi/

上传任务.component.ts

import  Component, OnInit, Input, ChangeDetectorRef  from '@angular/core';
import  AngularFireStorage, AngularFireUploadTask  from '@angular/fire/storage';
import  AngularFirestore  from '@angular/fire/firestore';
import  Observable  from 'rxjs';
import  finalize, tap  from 'rxjs/operators';

@Component(
  selector: 'upload-task',
  templateUrl: './upload-task.component.html',
  styleUrls: ['./upload-task.component.scss']
)
export class UploadTaskComponent implements OnInit 

  @Input() file: File;

  task: AngularFireUploadTask;

  percentage: Observable<number>;
  snapshot: Observable<any>;
  downloadURL: string;

  constructor(private storage: AngularFireStorage, private db: AngularFirestore)  

  ngOnInit() 
    this.startUpload();
  

  startUpload() 

    // The storage path
    const path = `test/$Date.now()_$this.file.name`;

    // Reference to storage bucket
    const ref = this.storage.ref(path);

    // The main task
    this.task = this.storage.upload(path, this.file);

    // Progress monitoring
    this.percentage = this.task.percentageChanges();

    this.snapshot   = this.task.snapshotChanges().pipe(
      tap(console.log),
      // The file's download URL
      finalize( async() =>  
        this.downloadURL = await ref.getDownloadURL().toPromise();

        this.db.collection('files').add(  downloadURL: this.downloadURL, path );
      ),
    );
  

  isActive(snapshot) 
    return snapshot.state === 'running' && snapshot.bytesTransferred < snapshot.totalBytes;
  


【讨论】:

以上是关于如何等待值然后返回一个对象的主要内容,如果未能解决你的问题,请参考以下文章

如何等待module.export函数完成请求,然后再将其返回值分配给不同JS文件中的变量[重复]

如何等待 Firebase 存储图像上传,然后运行下一个函数

Jquery:在返回之前等待回调

如何等待异步方法的回调返回值?

如何等待异步方法的回调返回值?

如何等待多个可观察流解决并一起返回它们