如何从Angular中的单个函数返回订阅和承诺?

时间:2020-10-23 06:33:50

标签: angular promise observable subscription

我正在一个实现了文件上传功能的有角项目中工作。 我创建了一个上传服务,并在其中创建了一个用于上传文件的功能

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。如何在promise中使用订阅并将其订阅到主机组件中。

我还考虑过将全局订阅变量添加到服务中并将其订阅到主机组件中。但是从多个位置上传文件并显示进度条时可能会导致问题。

我想使每个调用的订阅变量的作用域保持本地。

如果有人知道它,如何从promise函数广播值并从调用它的主机函数处接收..然后请答复此。对我很有帮助。

2 个答案:

答案 0 :(得分:1)

您应该从服务中返回一个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
        })
    }

答案 1 :(得分:0)

您可以将标头传递给您的http呼叫以订阅进度

True

在您上传组件中

v = ['Apple','Strawberry']
out = df.groupby('ID')['Fruit'].apply(lambda x: set(x) == set(v)).sum()
print (out)
2

OR

如果需要,您可以选择实施行为主题以实现此目的 在您的service.ts中,将processPercentage声明为行为主体

s = df.groupby('ID')['Fruit'].agg(set).value_counts()
print (s)
{Apple}                2
{Strawberry, Apple}    2
{Strawberry}           1
Name: Fruit, dtype: int64

在您的uploadComponent.ts

reportProgress: true,
observe: 'events'
相关问题