AngularJs优雅取消正在执行的http请求

一、前言

老规矩,每篇开篇之前先啰嗦一下吧。昨天刚刚把那个zip上传bug修复和新增一个上传进度条。今天在昨天的基础上提了更进步的需求,需要提供一个取消按钮,能够终止上传请求,目的是防止选择了错误的文件无法终止的情况,说到这,你们肯定会说断点续传和分片上传之类的,不过很不好意思,我上传的地方是一个动态的地址,没有后台接口支持我这么做,至少目前是这样的,据说以后会换成阿里的OSS,这个是支持断点和分片的,如果有重构的话,之后再续写了。

二、思路

  1. httpclient中有一个subscribe()方法,会返回一个promise对象,这个对象具有一个unsubscribe()方法,可以取消请求。
  2. 在类中定义一个属性缓存本次请求的promise对象
  3. 创建一个数组来缓存被取消请求的id属性
  4. 开启了reportProgress: true,接口会监听event,不断返回状态信息event,其包含type,loaded和total属性,通过(event.loaded/evet.total)*100可以计算出完成度的百分比。正是会不断执行subscribe()方法,即可在这个方法里面来做请求取消。

三、简单实例

import { Component, OnInit } from '@angular/core';
import { NzUploadFile, NzUploadXHRArgs, NzUploadChangeParam,UploadFilter } from 'ng-zorro-antd/upload';
import { NzMessageService } from 'ng-zorro-antd/message';
import { MyProfileCrudService } from '../../services/my-profile-crud.service';
import { HttpRequest, HttpClient, HttpHeaders, HttpEvent, HttpEventType, HttpResponse } from '@angular/common/http';
import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';

@Component({
  selector: 'app-consultation-list',
  templateUrl: './consultation-list.component.html',
  styleUrls: ['./consultation-list.component.scss']
})
export class ConsultationListComponent implements OnInit {
   
   private private canceler;
   
   constructor(private modal: NzModalService,
               public sanitizer: DomSanitizer,
               private _myProfileCrudService: MyProfileCrudService,
               private _http: HttpClient, 
               private _message: NzMessageService) {}
    
    //上传文件
    beforeUpload = (file: NzUploadFile): boolean => {
      const queryParams = {
        checkName: this.checkName
      }
      //获取上传文件url路径
      this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => {
        //上传路径
        const uploadUrl = data.data.body.urls.uploadUrl;
        this.aiCheckId = data.data.body.aiCheckId
        let File : any = file;
        //请求头        
        const headers = new HttpHeaders()
              .set('Content-Type','application/zip')
        //创建请求对象
        const request = new HttpRequest('PUT', uploadUrl, File as File, {
          headers,
          reportProgress: true,
        });
        //将subscribe方法的返回对象赋值给canceler
        this.canceler = this._http.request(request).subscribe(event => {
            console.log(event)
        })
    
      return false;
  };
  
  //取消上传请求
  cancelUploadRequest(){
    //取消请求
    this.canceler.unsubscribe();
  }
  
}

执行cancelUploadRequest方法即可取消http请求,简单吧!目前网上基本上没有相关资料,第一份哦!
在这里插入图片描述

四、文件上传取消示例

1. html代码示例

<nz-modal nzWidth="383px" height="415px" [(nzOkDisabled)]="isOkDisabled" [(nzVisible)]="isUploadVisible" nzTitle="上传影像数据" (nzOnCancel)="handleCancel()" (nzOnOk)="handleClickOk()">
    <div style="font-size:16px">
        名称
    </div>
    <div>
        <input nz-input style="
            width: 200px;
            height: 40px;
            background: #F1F1F1;
            border-radius: 6px;
            margin-top: 10px;" 
            class="uploader-input"
            type="text"  [(ngModel)]="checkName" placeholder="输入检测名称"/>
    </div>
    <nz-upload [(nzFileList)]="fileList" [nzMultiple]="true" nzListType=""
                [nzBeforeUpload]="beforeUpload" [nzFilter]="filters">
                <!-- <button [(disabled)]="!checkName" style="width: 300px; height: 40px;margin-top:26px;background: #F1F1F1;" nz-button><i nz-icon nzType="upload"></i>选择zip文件</button> -->
                <button nz-button [(disabled)]="!checkName || isUploadDisable" style="width: 160px;height: 160px;border-radius: 6px;border-style: dotted;border-color: #858585;
                            box-shadow: 0px 3px 8px 0px rgba(200,200,200,0.6);border-radius: 12px;
                            margin-top: 20px;text-align:center;color:black;">
                    <div style="width:100%;height:100%;font-size:60px;line-height: 130px;
                        text-align:center;color: #858585">
                            +
                            <div style="font-size: 12px;margin-top: -60px;">
                                选择zip文件上传
                            </div>
                    </div>
                </button>
    </nz-upload>

    <div style="width: 240px; height:40px;margin-top:26px">
        <nz-progress [(nzPercent)]="schedule" [nzStrokeColor]="{ '0%': '#B04FDD', '100%': '#B04FDD' }"></nz-progress>
    </div>

    <div *nzModalFooter>
        <button nz-button nzType="default" (click)="handleCancel()">取消</button>
        <button [(disabled)]="isOkDisabled" nz-button nzType="default" (click)="primary" style="color: #fff;
            background: #B04FDD;
            border-color: #1890ff;
            text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);
            box-shadow: 0 2px 0 rgb(0 0 0 / 5%);" (click)="handleClickOk()">
            确定
        </button>
      </div>
</nz-modal>

2. js代码示例

import { Component, OnInit } from '@angular/core';
import { NzUploadFile, NzUploadXHRArgs, NzUploadChangeParam,UploadFilter } from 'ng-zorro-antd/upload';
import { NzMessageService } from 'ng-zorro-antd/message';
import { MyProfileCrudService } from '../../services/my-profile-crud.service';
import { HttpRequest, HttpClient, HttpHeaders, HttpEvent, HttpEventType, HttpResponse } from '@angular/common/http';
import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';

@Component({
  selector: 'app-consultation-list',
  templateUrl: './consultation-list.component.html',
  styleUrls: ['./consultation-list.component.scss']
})
export class ConsultationListComponent implements OnInit {

  constructor(private modal: NzModalService,public sanitizer: DomSanitizer,private _myProfileCrudService: MyProfileCrudService,private _http: HttpClient, private _message: NzMessageService) { }

  public fileList: File[];
  public checkName : string = '';
  public schedule = '0';
  public isUploadVisible: boolean = false;
  public isUploadDisable: boolean = false;
  public isOkDisabled : boolean = true;
  public aiCheckId : number;
  public ingoreIds : number[] = [];
  private canceler ;

  //文件上传过滤器
  filters: UploadFilter[] = [
    {
      name: 'type',
      fn: (fileList: NzUploadFile[]) => {
        const filterFiles = fileList.filter(w => 
          w.name.search("zip")!=-1);
        if (filterFiles.length !== fileList.length) {
          this._message.error(`包含文件格式不正确,只支持 zip 格式`);
          return filterFiles;
        }
        return fileList;
      }
    },
    {
      name: 'async',
      fn: (fileList: NzUploadFile[]) => {
        if(!this.checkName){
          this._message.error(`请输入检查名称`);
          return null;
        }
        return fileList;
      }
    }
  ];



  ngOnInit(): void {
    
  }
  
  //添加执行记录
  handleClickOk(){
    if(this.schedule != '100.00' && this.schedule != '0'){
      this._message.warning("文件上传中...请耐心等候!")
      return;
    }
    if(this.aiCheckId){
      let payload = {
        id: this.aiCheckId,
        process: "-1",
      }
      this._myProfileCrudService.updateAiCheck(payload).subscribe(data=>{
        console.log(data)
        this._message.success("记录添加成功,请执行...")
        this.getAiExecuteRecords(true)
      })
    }
    this.isUploadVisible = false;
    
  }

  //取消请求,先加入取消数组中,待第二次执行时取消请求
  handleCancel(){
    this.confirmModal = this.modal.confirm({
      nzTitle: '是否取消?',
      nzContent: '点击确认后将放弃本次操作',
      nzOnOk: () =>{
        this.isUploadVisible = false;
        if(this.aiCheckId){
          this.ingoreIds.push(this.aiCheckId);
        }
      }
    });
  }

  //显示弹出窗口
  handleClick(){
    this.schedule = '0';
    this.checkName = '';
    this.isOkDisabled = false;
    this.isUploadVisible = true;
    this.isUploadDisable = false;
  }

  beforeUpload = (file: NzUploadFile): boolean => {
    if(!this.checkName){
      this._message.warning("请输入检查名称!")
      return;
    }
    const queryParams = {
      checkName: this.checkName
    }
    //获取文件上传地址
    this._myProfileCrudService.getAiUploadPath(queryParams).subscribe(data => {
      //上传路径
      const uploadUrl = data.data.body.urls.uploadUrl;
      this.aiCheckId = data.data.body.aiCheckId
      let File : any = file;
      //检查文件是否为zip文件,否则不提供上传服务
      if((File.name+"").search(".zip")==-1){
        this._message.warning("请上传zip文件!")
        return;
      }
      //请求头
      const headers = new HttpHeaders()
            .set('Content-Type','application/zip')
      //请求对象
      const request = new HttpRequest('PUT', uploadUrl, File as File, {
        headers,
        reportProgress: true,
      });
      //缓存promise对象
      let a = this._http
				.request(request).subscribe(event => {
          if(event.type == HttpEventType.UploadProgress){
            //如果在取消名单中,执行取消
            if(this.ingoreIds && this.ingoreIds.length && this.ingoreIds.indexOf(this.aiCheckId)!=-1){
              //取消请求
              this.canceler.unsubscribe();
            }
            this.schedule = ((event.loaded/event.total)*100).toFixed(2);
            console.log(this.schedule)
            if(!this.isOkDisabled){
              this.isOkDisabled = true;
            }
            if(!this.isUploadDisable){
              this.isUploadDisable = true;
            }
            
          }else if(event instanceof HttpResponse){
            console.log('File is completely uploaded!')
            this.isOkDisabled = false;
          }
          
      })
      this.canceler = a;
    })
    
    return false;
  };
}

然后文件上传服务就可以随时终止了,你不试一下?

      }else if(event instanceof HttpResponse){
        console.log('File is completely uploaded!')
        this.isOkDisabled = false;
      }
      
  })
  this.canceler = a;
})

return false;

};
}

然后文件上传服务就可以随时终止了,你不试一下?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笑不语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值