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


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

目录
相关文章
|
1月前
|
Rust 前端开发 API
Tauri 开发实践 — Tauri HTTP 请求开发
本文介绍了如何在 Tauri 中发起 HTTP 请求。首先通过安装 Tauri 生态中的工具包并配置 `tauri.conf.json` 文件来允许特定域名的 HTTP 通信。接着封装了一个简单的 HTTP 客户端类,并在页面中使用该客户端实现 GET 和 POST 请求。最后提供了完整的源码地址以供参考。此功能使得桌面应用能够与远程服务器进行交互,增强了应用的实用性。
91 1
Tauri 开发实践 — Tauri HTTP 请求开发
|
22天前
|
缓存 前端开发 API
|
27天前
|
数据采集 前端开发 算法
Python Requests 的高级使用技巧:应对复杂 HTTP 请求场景
本文介绍了如何使用 Python 的 `requests` 库应对复杂的 HTTP 请求场景,包括 Spider Trap(蜘蛛陷阱)、SESSION 访问限制和请求频率限制。通过代理、CSS 类链接数控制、多账号切换和限流算法等技术手段,提高爬虫的稳定性和效率,增强在反爬虫环境中的生存能力。文中提供了详细的代码示例,帮助读者掌握这些高级用法。
Python Requests 的高级使用技巧:应对复杂 HTTP 请求场景
|
11天前
|
JSON API 数据格式
Python中获取HTTP请求响应体的详解
本文介绍了如何使用Python的`requests`和`urllib`库发送HTTP请求并处理响应体。`requests`库简化了HTTP请求过程,适合快速开发;`urllib`库则更为底层,适用于性能要求较高的场景。文章详细演示了发送GET请求、处理JSON响应等常见操作。
|
9天前
|
安全 API 网络安全
使用OkHttp进行HTTPS请求的Kotlin实现
使用OkHttp进行HTTPS请求的Kotlin实现
|
16天前
|
前端开发 JavaScript Java
如何捕获和处理HTTP GET请求的异常
如何捕获和处理HTTP GET请求的异常
|
18天前
|
开发者
HTTP 协议请求方法的发展历程
【10月更文挑战第21天】
|
18天前
|
安全
HTTP 协议的请求方法
【10月更文挑战第21天】
|
18天前
|
缓存 安全 前端开发
HTTP 协议的请求方法在实际应用中有哪些注意事项?
【10月更文挑战第29天】HTTP协议的请求方法在实际应用中需要根据具体的业务场景和需求,合理选择和使用,并注意各种方法的特点和限制,以确保网络通信的安全、高效和数据的一致性。
|
22天前
|
安全 API 数据安全/隐私保护
常见的HTTP请求方法
【10月更文挑战第25天】这些HTTP请求方法共同构成了客户端与服务器之间交互的基础,使得客户端能够根据不同的需求对服务器资源进行各种操作。在实际应用中,开发者需要根据具体的业务场景和资源的性质选择合适的请求方法来实现客户端与服务器之间的有效通信。

热门文章

最新文章

下一篇
无影云桌面