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

简介: 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请求,简单吧!目前网上基本上没有相关资料,第一份哦!640.png


四、文件上传取消示例



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;
  };
}


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

目录
相关文章
|
2天前
|
存储 缓存 安全
第二章 HTTP请求方法、状态码详解与缓存机制解析
第二章 HTTP请求方法、状态码详解与缓存机制解析
|
2天前
|
Web App开发 存储 缓存
第八篇 提升网页性能:深入解析HTTP请求优化策略(三)
第八篇 提升网页性能:深入解析HTTP请求优化策略(三)
|
2天前
|
消息中间件 前端开发 JavaScript
第七篇 提升网页性能:深入解析HTTP请求优化策略(二)
第七篇 提升网页性能:深入解析HTTP请求优化策略(二)
|
2天前
|
缓存 自然语言处理 前端开发
第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述
第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述
|
2天前
|
安全 Android开发
Android之OKHttp基本使用和OKHttp发送https请求安全认证
Android之OKHttp基本使用和OKHttp发送https请求安全认证
11 0
|
3天前
状态码对于理解HTTP请求和响应的流程,以及调试网络问题非常重要
【5月更文挑战第15天】HTTP状态码由三位数字表示,分为1xx-5xx五类。1xx为信息响应,2xx表示成功,如200(请求成功)、201(创建成功)。3xx是重定向,如301(永久移动)、302(临时重定向)。4xx表示客户端错误,如400(坏请求)、404(未找到)。5xx是服务器错误,包括500(内部服务器错误)和503(服务不可用)。这些状态码用于理解请求响应流程和调试网络问题。
9 1
|
1天前
|
缓存 前端开发 JavaScript
React和Next.js开发常见的HTTP请求方法
React和Next.js开发常见的HTTP请求方法
5 0
|
1天前
|
自然语言处理 负载均衡 监控
处理HTTP请求的服务器
处理HTTP请求的服务器
10 1
|
1天前
|
JSON Java 数据安全/隐私保护
java中的http请求的封装(GET、POST、form表单、JSON形式、SIGN加密形式)
java中的http请求的封装(GET、POST、form表单、JSON形式、SIGN加密形式)
|
2天前
|
编解码 前端开发 JavaScript
第六篇 提升网页性能:深入解析HTTP请求优化策略(一)
第六篇 提升网页性能:深入解析HTTP请求优化策略(一)