簡體   English   中英

如何從角度中的單個函數返回訂閱和承諾?

[英]How to return subscription and promise from single function in angular?

我正在開發一個 angular 項目,其中實現了文件上傳功能。 我創建了一個上傳服務並在其中創建了一個用於上傳文件的功能

service.ts :

upload(file: File){
  return new Promise(resolve=>{
    var file = file;
    bucket.upload(file).on("httpUplaodprogress", (progress)=>{
        const percent = progress.percent

        -->  Here I want to emit this percent value from this function. and want to get it where it is from called.


    }).send(response =>{
      response.error ? reject(response.err);
      resolve(response);
    })
  })
}

現在很多地方都在使用這個上傳服務。

例如:

uploadComponent.ts :

progress:number = 0;

constructor(private uploadService: UploadService) {}

handleFileInput(file){
    this.uploadService.upload(file).then(result=>{
       result ? show success msg for file uplaod success : show error

       ==> I want to subscribe service's upload function's progress variable 
           here for assign that value into this host component's progress variable which is 
           bind with progressbar copmponent.
   
    })
}

uploadComponent.html

<progressbar [progress]="progress" />

這是當前的場景,我們無法將服務函數中的進度變量訪問到調用服務函數的主機組件中。

一種方法是,我們可以在宿主組件中獲取訂閱服務功能,並且可以不斷獲取進度值。 但是怎么樣?

因為服務功能已經返回承諾。 如何在 promise 中使用訂閱並將其訂閱到主機組件中。

我還考慮過將全局訂閱變量加入服務並將其訂閱到主機組件中。 但是從多個地方上傳文件並顯示進度條時可能會導致問題。

我想為每次調用保留訂閱變量的本地范圍。

如果有人知道它,如何從承諾函數廣播值並從它被調用的地方接收主機函數..然后請回復這個。 這對我很有幫助。

你應該從你的服務中返回一個 Observable 而不是一個 Promise。

UploadService

// note that BucketUploadResponse is an interface I made up
upload(file: File): Promise<BucketUploadResponse> {
     // delegate to our Observable implementation and convert to promise
     return this.upload$(file).toPromise();
}

// note that BucketUploadResponse is an interface I made up
upload$(file: File): Observable<number | BucketUploadResponse> {
        return new Observable<number>((subscriber) => {
            bucket
                .upload(file)
                .on('httpUplaodprogress', (progress) => {
                    const percent = progress.percent;
                    // emit progress
                    subscriber.next(percent);
                })
                .send((response) => {
                    if (response.error) {
                        // error out
                        subscriber.error(response.error);
                    } else {
                        // emit response as last item to keep old contract
                        subscriber.next(response);
                        subscriber.complete();
                    }
                });

            return () => {
                // called when no subscription is left. You could abort the upload here for example
            };
        });
    }

在消費組件中,您可以訂閱 Observable:

    progress:number = 0;
    
    private uploadSubscription?: Subscription;

    constructor(private uploadService: UploadService) {}

    handleFileInput(file){
        this.progress = 0;
        // unsubscribe from an existing upload
        this.uploadSubscription?.unsubscribe();
        this.uploadSubscription = this.uploadService.upload(file).subscribe((progress) => {
            if (typeof progress === 'number') {
                this.progress = progress;
            } else {
                // handle BucketUploadResponse if required
            }
        }, () => {
            // complete, show success message
        }, (error) => {
            // error, show error message
        })
    }

您可以將標頭傳遞給您的 http 調用以訂閱進度

reportProgress: true,
observe: 'events'

在你上傳組件

yourservice.subscribe((e: HttpEvent<any>) => {
          switch (e.type) {
            case HttpEventType.Sent:
              break;
            case HttpEventType.ResponseHeader:
              break;
            case HttpEventType.UploadProgress:
              this.progress = Math.round(e.loaded / e.total * 100);
              break;
            case HttpEventType.Response:
              this.progress = -1;
          }
    });

或者

如果您願意,您可以選擇實施行為主題來實現這一點在您的 service.ts 中將 processPercentage 聲明為行為主題

const percent = progress.percent;
this.processPercentage.next(percent);

在你的 uploadComponent.ts

subscription:Subscription;
constructor(private uploadService: UploadService,private service:Service) {}
ngOnInit(){
 this.getProgress();
}

getProgress(){
 this.subscription = 
 this.service.processPercentage.asObservable().susbcribe((progress) => {
  this.progress = progress;
  console.log(this.progress);
  // You can bind to your progressbar from here 
 });
}

ngOnDestroy(){
 this.subscription.unsubscribe();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM