让fetch也可以timeout

本文作者:IMWeb zzbozheng 原文出处:IMWeb社区 未经同意,禁止转载

原生的HTML5 API fetch并不支持timeout属性,习惯了jQuery的ajax配置的同学,如果一时在fetch找不到配置timeout的地方,也许会很纠结。fetch 的配置 API 如下:

语法

fetch(input, init).then(function(response) { ... });

参数

  • input

定义要获取的资源。这可能是: 一个 USVString 字符串,包含要获取资源的 URL。 一个 Request 对象。

  • init 可选 一个配置项对象,包括所有对请求的设置。可选的参数有:

method: 请求使用的方法,如 GET、POST。 headers: 请求的头信息,形式为 Headers 对象或 ByteString。 body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。 mode: 请求的模式,如 cors、 no-cors 或者 same-origin。 credentials: 请求的 credentials,如 omit、same-origin 或者 include。 cache: 请求的 cache 模式: default, no-store, reload, no-cache, force-cache, or only-if-cached.

根本找不到timeout配置,本文和大家分享如何快速实现 fetch 的 timeout功能。

我们先实现abort功能,但由于初始化fetch后,返回的是一个Promise对象,那么需要在abort后达到触发rejectPromise的效果。

如果要沿用fetch返回的Promise来实现abort估计是达不到效果的,这里需要借助自己的一个Promise实例来达到目的。

var abort_fn = null;
var abort_promise = new Promise(function(resolve, reject) {
     abort_fn = function() {
         reject('abort promise');
     };
 });

这个简单的代码段,可以通过调用abort_fn 函数就可以触发abort_promise的reject

fetch 返回的promise 我们暂且称为 fetch_promise 吧,那么现在有两个 promise:abort_promisefetch_promise

每个promise都可以绑定resolve callback 和 reject callbck,那么后续then的回调绑定到哪个promise上呢,这是一个问题。

这里我们使用Promise非常好用的Promise.race方法, 他可以帮我们解决这个问题:

Promise.race 概述 Promise.race(iterable)方法返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后,立刻以相同的解决值被解决或以相同的拒绝原因被拒绝。

合体:

function abortablePromise(fetch_promise) {
      var abort_fn = null;

      //这是一个可以被reject的promise
      var abort_promise = new Promise(function(resolve, reject) {
             abort_fn = function() {
                  reject('abort promise');
              };
      });

      //这里使用Promise.race,以最快 resolve 或 reject 的结果来传入后续绑定的回调
       var abortable_promise = Promise.race([
             fetch_promise,
             abort_promise
       ]);

       abortable_promise.abort = abort_fn;

       return abortable_promise;
}

经过abortablePromise包裹后的promise都会返回一个新的promise,不同的是带上了一个abort方法。 使用例子:

var p = abortablePromise(fetch('//a.com/b/c'));
p.then(function(res) {
    console.log(res)
}, function(err) {
    console.log(err);
});

//假设fetch要3秒,但是你想在2秒就放弃了:
setTimeout(function() {
    p.abort(); // -> will print "abort promise"
}, 2000);

目前为止,大体功能已经实现,再稍微调整,让调用更方便:

function _fetch(fetch_promise, timeout) {
      var abort_fn = null;

      //这是一个可以被reject的promise
      var abort_promise = new Promise(function(resolve, reject) {
             abort_fn = function() {
                reject('abort promise');
             };
      });

      //这里使用Promise.race,以最快 resolve 或 reject 的结果来传入后续绑定的回调
       var abortable_promise = Promise.race([
             fetch_promise,
             abort_promise
       ]);

       setTimeout(function() {
             abort_fn();
        }, timeout);

       return abortable_promise;
}

//usage:
_fetch(fetch('//a.com/b/c'), 2000)
    .then(function(res) {
        console.log(res)
    }, function(err) {
        console.log(err);
    });

全文完

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开源优测

21条自动化测试过程中遭遇的问题及解决思路

1、找不到元素,脚本报“NoSuchElementException:Unable to find element”,或者"定位到了,不能操作,点击无效"

65230
来自专栏python3

Django的路由控制

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于...

40220
来自专栏老马寒门IT

jQuery的ajax详解

jQuery内部也封装了对原生ajax请求的方法,可以很方便我们的对后台异步请求处理。

14600
来自专栏禅林阆苑

vim按键整理 【原创】

vim按键整理 Write By CS逍遥剑仙 我的主页: www.csxiaoyao.com GitHub: github.com/csxi...

361100
来自专栏calmound

getchar

跟你分享个东西,我也是刚刚在网上查到的,和我想的差不多,呵呵~~~~ getchar是以行为单位进行存取的。 当用getchar进行输入时,如果输入的第一个字符...

37760
来自专栏我的博客

坑爹的BOM

场景:开发小程序使用wx.request请求数据时提示Cannot read property of ‘xxxx’ undefined…….. ...

341100
来自专栏xcywt

《Linux命令行与shell脚本编程大全》第二十一章 sed进阶

本章介绍一些sed编辑器提供的高级特性。 21.1 多行命令 按照之前的知识,所有的sed编辑器命令都是针对单行数据执行操作的。 在sed编辑器读取数据流时,它...

24490
来自专栏Danny的专栏

实时错误'453':找不到DLL入口点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

20920
来自专栏凉城

WordPress 如何判断一篇文章是否存在

25440
来自专栏开源优测

21条自动化测试过程中遭遇的问题及解决思路

1、找不到元素,脚本报“NoSuchElementException:Unable to find element”,或者"定位到了,不能操作,点击无效"

11010

扫码关注云+社区

领取腾讯云代金券