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


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

目录
相关文章
|
5月前
|
JSON 监控 API
掌握使用 requests 库发送各种 HTTP 请求和处理 API 响应
本课程全面讲解了使用 Python 的 requests 库进行 API 请求与响应处理,内容涵盖环境搭建、GET 与 POST 请求、参数传递、错误处理、请求头设置及实战项目开发。通过实例教学,学员可掌握基础到高级技巧,并完成天气查询应用等实际项目,适合初学者快速上手网络编程与 API 调用。
583 130
|
8月前
|
JavaScript 前端开发 API
Node.js中发起HTTP请求的五种方式
以上五种方式,尽管只是冰山一角,但已经足以让编写Node.js HTTP请求的你,在连接世界的舞台上演奏出华丽的乐章。从原生的 `http`到现代的 `fetch`,每种方式都有独特的风格和表现力,让你的代码随着项目的节奏自由地舞动。
769 65
|
6月前
HTTP协议中请求方式GET 与 POST 什么区别 ?
GET和POST的主要区别在于参数传递方式、安全性和应用场景。GET通过URL传递参数,长度受限且安全性较低,适合获取数据;而POST通过请求体传递参数,安全性更高,适合提交数据。
639 2
|
7月前
|
Go 定位技术
Golang中设置HTTP请求代理的策略
在实际应用中,可能还需要处理代理服务器的连接稳定性、响应时间、以及错误处理等。因此,建议在使用代理时增加适当的错误重试机制,以确保网络请求的健壮性。此外,由于网络编程涉及的细节较多,彻底测试以确认代理配置符合预期的行为也是十分重要的。
307 8
|
7月前
|
缓存
|
6月前
|
JSON JavaScript API
Python模拟HTTP请求实现APP自动签到
Python模拟HTTP请求实现APP自动签到
|
11月前
|
JSON API 网络架构
HTTP常见的请求方法、响应状态码、接口规范介绍
本文详细介绍了HTTP常见的请求方法、响应状态码和接口规范。通过理解和掌握这些内容,开发者可以更好地设计和实现W
1824 83
|
6月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
7月前
|
缓存 JavaScript 前端开发
Vue 3 HTTP请求封装导致响应结果无法在浏览器中获取,尽管实际请求已成功。
通过逐项检查和调试,最终可以定位问题所在,修复后便能正常在浏览器中获取响应结果。
305 0
|
7月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
526 0