范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

嗯,还在用Ajax嘛?Fetch了解一下呀

  写在前面之前写了一篇 AJAX 相关的博文的,看到有小伙伴讲到了Fetch ,所以研究下 博文内容参考:   https://www.ruanyifeng.com/blog/2020/12/fetch-tutorial.html  https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API  https://github.com/node-fetch/node-fetch  https://github.com/github/fetch  Demo 是搭了一个简单的Flask web服务,然后通过Node 环境发出请求
  「此刻你在沙漠里,因此你要潜心于沙漠之中。沙漠和世上其他东西一样,可以用来理解世界。你甚至不必理解沙漠,只要观察普通的沙粒就行,从中你可以看到天地万物的神奇之处。--------《牧羊少年的人生之旅》」
  Fetch API  提供了一个获取资源的接口(包括跨域请求)。任何使用过XMLHttpRequest 的人都能轻松上手,而且新的 API 提供了更强大和灵活的功能集。
  Fetch  提供了对Request 和Response ,Headers (以及其他与网络请求有关的)对象的通用定义
  fetch()  必须接受一个参数——资源的路径。无论请求成功与否,它都返回一个Promise 对象,resolve  对应请求的 Response 。你也可以传一个可选的第二个参数 init 。
  一旦 Response 被返回,就可以使用一些方法来定义内容的形式,以及应当如何处理内容,你也可以通过 Request() 和 Response() 的构造函数直接创建请求和响应,但是我们不建议这么做。 Fetch 接口Headers :相当于 response/request 的头信息 Request :相当于一个资源请求 Response :相当于请求的响应 使用 Fetch
  Fetch API  提供了一个JavaScript 接口,用于访问和操纵 HTTP 管道 的一些具体部分,例如请求和响应。它还提供了一个全局fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
  fetch 规范与 jQuery.ajax() 主要有以下的不同: 当接收到一个代表错误的  HTTP 状态码 时,从 fetch() 返回的Promise 不会被标记为 reject ,即使响应的 HTTP 状态码 是 404 或 500 。相反,它会将Promise 状态标记为 resolve  (如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject 。 +fetch 不会发送跨域 cookies ,除非你使用了credentials 的初始化选项。(自2018 年 8 月以后,默认的 credentials 政策变更为 same-origin 。Firefox 也在 61.0b13 版本中进行了修改) fetch() 使用 Promise ,不使用回调函数 ,因此大大简化了写法,写起来更简洁。 fetch() 采用模块化设计 ,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象 ),更合理一些;相比之下,XMLHttpRequest  的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码。 fetch()通过数据流(Stream 对象)处理数据 ,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件或者网速慢的场景相当有用。XMLHTTPRequest 对象不支持数据流,所有的数据必须放在缓存里,不支持分块读取,必须等待全部拿到后,再一次性吐出来。
  在用法上, fetch() 接受一个URL 字符串作为参数,默认向该网址发出GET 请求,返回一个 Promise  对象。 环境准备
  这里我们用 Node 环境来学习,当然在浏览器更有可比性,需要安装基于Node 的依赖包node-fetch ,这里一定要注意版本问题 node-fetch 用于服务器端 ,即只能在nodejs 中用 whatwg-fetch 用于客户端 ,即用于在浏览器没有原生支持fetch 的情况 isomorphic-fetch 可以在nodejs 和浏览器 两种环境中运行,是对whatwg-fetch 的包装 。 npm install node-fetch@2
  同时我们需要一个 Web 服务用作测试,这里用python 搭一个简单的Web 服务 #!/usr/bin/env python3 # -*- encoding: utf-8 -*- # Python 3.9.0 # pip install flask """ @File    :   fetch.py @Time    :   2022/03/04 18:59:02 @Author  :   Li Ruilong @Version :   1.0 @Contact :   1224965096@qq.com @Desc    :   Fetch学习Demo """  from time import sleep from flask import Flask,jsonify,request,send_from_directory import os  # configuration DEBUG = True  app = Flask(__name__)    @app.route("/") @app.route("/index") def default():     """     @Time    :   2022/03/04 18:58:42     @Author  :   Li Ruilong     @Version :   1.0     @Desc    :   默认页面     """     return "

Fetch学习Demo

" @app.route("/init", methods=["GET"]) def init(): """ @Time : 2022/03/04 19:41:40 @Author : Li Ruilong @Version : 1.0 @Desc : get请求返回JSON """ data = ["Ajax","Fetch","Promise","Axios"] return jsonify(data) @app.route("/add",methods=["POST"]) def add(): """ @Time : 2022/03/04 19:43:05 @Author : Li Ruilong @Version : 1.0 @Desc : Post请求 """ data = request.json print(*data, sep=" ") return jsonify({"msg":"Post请求成功","code":"0"}) @app.route("/download/") def download(filename): print(filename) """ @Time : 2022/03/04 22:30:12 @Author : Li Ruilong @Version : 1.0 @Desc : 下载文件 """ directory = os.getcwd() print(directory) return send_from_directory(directory, filename, as_attachment=True) @app.route("/upload", methods=["POST", "PUT"]) def upload(): """ @Time : 2021/12/15 10:32:03 @Author : Li Ruilong @Version : 1.0 @Desc : 上传文件 """ if request.method == "POST": try: f = request.files["file"] print("上传的文件名:===", f.filename) basepath = os.path.dirname(__file__) # 当前文件所在路径 upload_path = os.path.join(basepath, "", str(f.filename)) f.save(upload_path) print("保存的文件路径:"+upload_path) except Exception as e: print("上传文件失败", e) return jsonify({"msg":"上传文件OK","code":"0"}),200 @app.route("/stop/") def stop(s): sleep(s) return "OK",200 if __name__ == "__main__": app.run(host="127.0.0.1", port=37881, debug=DEBUG)   data.json文件 [ { "site": "npr", "link": "http://www.npr.org/rss/rss.php?id=1001", "type": "rss" }, { "site": "npr", "link": "http://www.npr.org/rss/rss.php?id=1008", "type": "rss" } ]   准备工作做好以后,我们开始愉快的学习吧   一个基本的 fetch 请求设置起来很简单。看看下面的代码:   这是一个回调风格的请求,从服务器获取 JSON 数据。在Node 环境的一个Demo // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); fetch("http://127.0.0.1:37881/download/data.json") .then(response => response.json()) .then(json => console.log(json)) .catch(err => console.log("Request Failed", err));   fetch() 接收到的response 是一个Stream 对象,response.json() 是一个异步操作,取出所有内容,并将其转为 JSON 对象 。   整理上看和 axios 类似,相同点都是基于ES 6 的Promise 对象,在Node 环境,都是基于HTTP模块 实现,不同点,axios 在浏览器中,是基于XMLHttpRequests 来实现异步通信的,而fetch 是一个新的API ,是XMLHttpRequest 的最新替代技术 ,下面是一个axios 的例子. const axios = require("axios").default; const { v4: uuidv4 } = require("uuid"); let subscriptionKey = "3c6588c7026b41a4**7f81551cb4a737"; let endpoint = "https://api.translator.azure.cn/"; let location = "chinanorth"; axios({ baseURL: endpoint, url: "/translate", method: "post", headers: { "Ocp-Apim-Subscription-Key": subscriptionKey, "Ocp-Apim-Subscription-Region": location, "Content-type": "application/json", "X-ClientTraceId": uuidv4().toString() }, params: { "api-version": "3.0", "from": "zh-Hans", "to": ["zh-Hant", "en"] }, data: [{ "text": "我徒然学会了抗拒热闹,却还来不及透悟真正的冷清。--------张大春" }], responseType: "json" }).then(function(response){ console.log(JSON.stringify(response.data, null, 4)); }).catch(function (error) { console.log(error); });   Promise 可以使用await 语法改写,使得语义更清晰。 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/download/data.json"; try { let response = await fetch(url); let data =await response.json(); console.log(data); } catch (e) { console.log("Oops, error", e); } })()   await 语句必须放在try...catch 里面,这样才能捕捉异步 操作中可能发生的错误 . ===== PS D:GolandProjectscode-masterdemo> node fetch [ { site: "npr", link: "http://www.npr.org/rss/rss.php?id=1001", type: "rss" }, { site: "npr", link: "http://www.npr.org/rss/rss.php?id=1008", type: "rss" } ] PS D:GolandProjectscode-masterdemo> Response 对象:处理 HTTP 回应   fetch() 请求成功以后,得到的是一个Response 对象。它对应服务器的 HTTP 回应 。 const response = await fetch(url);   Response 包含de同步属性,对应 HTTP 回应的标头信息(Headers) ,可以立即读取 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/init"; try { let response = await fetch(url); //同步属性,对应 HTTP 回应的标头信息(Headers),可以立即读取 console.log(response.ok); console.log(response.status); console.log(response.statusText); console.log(response.type); console.log(response.url); console.log(response.redirected) //Response 包含的数据通过 Stream 接口异步读取 let data =await response.json(); console.log(data); } catch (e) { console.log("Oops, error", e); } })() [Running] node "d:GolandProjectscode-masterdemofetch.js" true 200 OK undefined http://127.0.0.1:37881/init false [ "Ajax", "Fetch", "Promise", "Axios" ] [Done] exited with code=0 in 0.253 seconds   response.ok :属性返回一个布尔值,表示请求是否成功,true对应 HTTP 请求的状态码 200 到 299,false对应其他的状态码。   response.status :属性返回一个数字,表示 HTTP 回应的状态码(例如200,表示成功请求)。   response.statusText :属性返回一个字符串,表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回"OK")。   response.url :属性返回请求的 URL。如果 URL 存在跳转,该属性返回的是最终 URL。   response.type :属性返回请求的类型。可能的值如下: 通过状态码判断请求是否成功// -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/init"; try { let response = await fetch(url); if (response.status >= 200 && response.status < 300){ let data = await response.json(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })()   我们把python的web服务接口里抛出一个异常,直接到了catch里面 @app.route("/init", methods=["GET"]) def init(): """ @Time : 2022/03/04 19:41:40 @Author : Li Ruilong @Version : 1.0 @Desc : get请求返回JSON """ data = ["Ajax","Fetch","Promise","Axios"] raise Exception("这是一个请求异常的模拟") return jsonify(data)   执行报错:内部服务器错误,即 500 [Running] node "d:GolandProjectscode-masterdemofetch.js" Oops, error Error: INTERNAL SERVER ERROR at d:GolandProjectscode-masterdemofetch.js:23:15 at processTicksAndRejections (internal/process/task_queues.js:93:5)   修改接口返回状态码为 400 @app.route("/init", methods=["GET"]) def init(): """ @Time : 2022/03/04 19:41:40 @Author : Li Ruilong @Version : 1.0 @Desc : get请求返回JSON """ data = ["Ajax","Fetch","Promise","Axios"] return jsonify(data),400   报错误请求 [Running] node "d:GolandProjectscode-masterdemofetch.js" INTERNAL SERVER ERROR Oops, error Error: INTERNAL SERVER ERROR at d:GolandProjectscode-masterdemofetch.js:24:19 at processTicksAndRejections (internal/process/task_queues.js:93:5) [Done] exited with code=0 in 0.261 seconds   也可以直接通过 response.ok 来判断 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/init"; try { let response = await fetch(url); if (response.ok){ let data = await response.json(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })()   修改接口返回状态码为 404 @app.route("/init", methods=["GET"]) def init(): """ @Time : 2022/03/04 19:41:40 @Author : Li Ruilong @Version : 1.0 @Desc : get请求返回JSON """ data = ["Ajax","Fetch","Promise","Axios"] return jsonify(data),404 [Running] node "d:GolandProjectscode-masterdemofetch.js" NOT FOUND Oops, error Error: NOT FOUND at d:GolandProjectscode-masterdemofetch.js:24:19 at processTicksAndRejections (internal/process/task_queues.js:93:5) [Done] exited with code=0 in 0.257 seconds Response.headers 属性   Response 对象还有一个Response.headers 属性,指向一个Headers 对象,对应 HTTP 回应的所有标头。   Headers 对象可以使用for...of 循环进行遍历。 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/init"; try { let response = await fetch(url); if (response.ok){ let data = await response.json(); console.log(data); for (let [key, value] of response.headers) { //console.log(key+":"+ value); console.log(`${key} : ${value}`); } return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })() [Running] node "d:GolandProjectscode-masterdemofetch.js" [ "Ajax", "Fetch", "Promise", "Axios" ] content-length : 51 content-type : application/json date : Sat, 05 Mar 2022 15:14:47 GMT server : Werkzeug/2.0.2 Python/3.9.0 [Done] exited with code=0 in 0.26 seconds   Headers 对象提供了以下方法,用来操作标头。HTTP 回应来说,修改标头意义不大 Headers.get() :根据指定的键名,返回键值。 Headers.has() : 返回一个布尔值,表示是否包含某个标头。 Headers.set() :将指定的键名设置为新的键值,如果该键名不存在则会添加。 Headers.append() :添加标头。 Headers.delete() :删除标头。 Headers.keys() :返回一个遍历器,可以依次遍历所有键名。 Headers.values() :返回一个遍历器,可以依次遍历所有键值。 Headers.entries() :返回一个遍历器,可以依次遍历所有键值对([key, value])。 Headers.forEach() :依次遍历标头,每个标头都会执行一次参数函数。 读取内容的方法   Response 对象根据服务器返回的不同类型的数据,提供了不同的读取方法。读取方法都是异步的 ,返回的都是 Promise 对象。必须等到 异步操作结束,才能得到服务器返回的 完整数据`。 response.text() :得到文本字符串。 response.json() :得到 JSON 对象。 response.blob() :得到二进制 Blob 对象。 response.formData() :得到 FormData 表单对象。 response.arrayBuffer() :得到二进制 ArrayBuffer 对象。   「response.text()可以用于获取文本数据,比如HTML文件。」 @app.route("/") @app.route("/index") def default(): """ @Time : 2022/03/04 18:58:42 @Author : Li Ruilong @Version : 1.0 @Desc : 默认页面 """ return "

Fetch学习Demo

" // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/"; try { let response = await fetch(url); if (response.ok){ let data = await response.text(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })()   「response.json() 主要用于获取服务器返回的 JSON 数据」   「response.formData()主要用在 Service Worker 里面,拦截用户提交的表单,修改某些数据以后,再提交给服务器。」   「response.blob()用于获取二进制文件。」 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/download/data.json"; try { let response = await fetch(url); if (response.ok){ let data = await response.blob(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })() [Running] node "d:GolandProjectscode-masterdemofetch.js" Blob { [Symbol(type)]: "application/json", [Symbol(buffer)]: } [Done] exited with code=0 in 0.847 seconds   response.arrayBuffer()主要用于获取流媒体文件。 const audioCtx = new window.AudioContext(); const source = audioCtx.createBufferSource(); const response = await fetch("song.ogg"); const buffer = await response.arrayBuffer(); const decodeData = await audioCtx.decodeAudioData(buffer); source.buffer = buffer; source.connect(audioCtx.destination); source.loop = true; Response.clone()   Stream 对象 只能读取一次,读取完就没了。这意味着,前一节的五个读取方法,只能使用一个,否则会报错。   Response 对象提供Response.clone() 方法,创建Response对象的副本 ,实现多次读取。 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/download/data.json"; try { let response = await fetch(url); let response1 = response.clone(); if (response.ok){ let data = await response.json(); let data1 = await response1.json() console.log(data1); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })() [Running] node "d:GolandProjectscode-masterdemofetch.js" [ { site: "npr", link: "http://www.npr.org/rss/rss.php?id=1001", type: "rss" }, { site: "npr", link: "http://www.npr.org/rss/rss.php?id=1008", type: "rss" } ] [Done] exited with code=0 in 0.25 seconds   Response 对象还有一个 Response.redirect() 方法,用于将 Response 结果重定向到指定的 URL。该方法一般只用在 Service Worker 里面 Response.body 属性   Response.body 属性是 Response 对象暴露出的底层接口,返回一个 ReadableStream 对象,供用户操作。   它可以用来分块读取内容,应用之一就是显示下载的进度。 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { let url = "http://127.0.0.1:37881/download/data.json"; fetch(url) .then(response => response.body) .then(res => res.on("readable", () => { let chunk; while (null !== (chunk = res.read())) { console.log(chunk.toString()); } })) .catch(err => console.log(err)); })() 第二个参数init:定制 HTTP 请求   fetch() 的第一个参数是 URL ,还可以接受第二个参数 ,作为配置对象 ,定制发出的HTTP 请求 。   HTTP 请求的方法、标头、数据体都在这个对象里面设置 Post请求传递JSON@app.route("/add",methods=["POST"]) def add(): """ @Time : 2022/03/04 19:43:05 @Author : Li Ruilong @Version : 1.0 @Desc : Post请求 """ data = request.json print(*data, sep=" ") return jsonify({"msg":"Post请求成功","code":"0"}) // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); (async () => { const url = "http://127.0.0.1:37881/add"; const body = { name: "John", surname: "Smith" }; try { let response = await fetch(url,{ method: "post", body: JSON.stringify(body), headers: {"Content-Type": "application/json;charset=utf-8"} }); if (response.ok){ const data = await response.json(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })() name surname 127.0.0.1 - - [06/Mar/2022 02:27:42] "POST /add HTTP/1.1" 200 - ======== [Running] node "d:GolandProjectscode-masterdemofetch.js" { code: "0", msg: "Post请求成功" } [Done] exited with code=0 in 0.293 seconds 文件上传@app.route("/upload", methods=["POST", "PUT"]) def upload(): """ @Time : 2021/12/15 10:32:03 @Author : Li Ruilong @Version : 1.0 @Desc : 上传文件 """ if request.method == "POST": try: f = request.files["file"] print("上传的文件名:===", f.filename) basepath = os.path.dirname(__file__) # 当前文件所在路径 upload_path = os.path.join(basepath, "", str(f.filename)) f.save(upload_path) print("保存的文件路径:"+upload_path) except Exception as e: print("上传文件失败", e) return jsonify({"msg":"上传文件OK","code":"0"}),200 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fs = require("fs"); const fetch = require("node-fetch"); const FormData = require("form-data"); let fileStream = fs.readFileSync("./data.json");//读取文件 let formdata = new FormData(); const mimetype = "text/plain" formdata.append("file", fileStream, { filename: "./data.json",//上传的文件名 contentType: mimetype,//文件类型标识 }); (async () => { const url = "http://127.0.0.1:37881/upload"; try { let response = await fetch(url,{ method: "post", body: formdata , headers: formdata.getHeaders() }); if (response.ok){ const data = await response.json(); console.log(data); return data; }else{ console.log(response.statusText); throw new Error(response.statusText); } } catch (e) { console.log("Oops, error", e); } })() 上传的文件名:=== data.json 保存的文件路径:d:data.json 127.0.0.1 - - [06/Mar/2022 01:37:51] "POST /upload HTTP/1.1" 200 - ============ [Running] node "d:GolandProjectscode-masterdemofetch.js" { code: "0", msg: "上传文件OK" } fetch()配置对象的完整 APIconst response = fetch(url, { method: "GET", headers: { "Content-Type": "text/plain;charset=UTF-8" }, body: undefined, referrer: "about:client", //referrer属性用于设定fetch()请求的referer标头。 referrerPolicy: "no-referrer-when-downgrade", //referrerPolicy属性用于设定Referer标头的规则 mode: "cors", // mode属性指定请求的模式 credentials: "same-origin", //credentials属性指定是否发送 Cookie。 cache: "default", //cache属性指定如何处理缓存 redirect: "follow", //redirect属性指定 HTTP 跳转的处理方法 integrity: "", //integrity属性指定一个哈希值,用于检查 HTTP 回应传回的数据是否等于这个预先设定的哈希值。 keepalive: false, /// keepalive属性用于页面卸载时,告诉浏览器在后台保持连接,继续发送数据。 signal: undefined //signal属性指定一个 AbortSignal 实例,用于取消fetch()请求 }); 取消fetch()请求   fetch() 请求发送以后,如果中途想要取消,需要使用AbortController 对象。 @app.route("/stop/") def stop(s): sleep(s) return "OK",200   请求进去 睡眠10s ,在5s 的时候终止请求 ,新建AbortController 实例,然后发送fetch() 请求,配置对象的signal 属性必须指定接收AbortController 实例发送的信号controller.signal 。   controller.abort() 方法用于发出取消信号。这时会触发abort事件 ,这个事件可以监听,也可以通过controller.signal.aborted 属性判断取消信号是否已经发出 // -*- encoding: utf-8 -*- /* *@File : fetch.js *@Time : 2022/03/04 22:04:04 *@Author : Li Ruilong *@Version : 1.0 *@Contact : 1224965096@qq.com *@Desc : Fetch学习 */ const fetch = require("node-fetch"); //npm install abort-controller const AbortController = globalThis.AbortController || require("abort-controller") const controller = new AbortController(); const timeout = setTimeout(() => { controller.abort(); }, 5000); (async () => { const url = "http://127.0.0.1:37881/stop/10"; try { const response = await fetch(url, {signal: controller.signal}); const data = await response.text(); console.log(data) } catch (error) { console.log("request was aborted",error); } finally { clearTimeout(timeout); } })() [Running] node "d:GolandProjectscode-masterdemofetch.js" request was aborted AbortError: The user aborted a request.   「Node 环境」 PS D:GolandProjectscode-masterdemo> node -v v12.13.1 PS D:GolandProjectscode-masterdemo> npm -v 6.12.1 PS D:GolandProjectscode-masterdemo> npm init -y { "name": "demo", "version": "1.0.0", "description": "", "main": "fetch.js", "dependencies": { "abort-controller": "^3.0.0", "form-data": "^4.0.0", "node-fetch": "^2.6.7" }, "devDependencies": {}, "scripts": { "test": "echo "Error: no test specified" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }   「python 环境」 PS D:GolandProjectscode-master> python -V Python 3.9.0 PS D:GolandProjectscode-master> pip -V pip 20.2.3 from d:pythonpython310libsite-packagespip (python 3.9) PS E:docker> flask --version Python 3.9.0 Flask 2.0.2 Werkzeug 2.0.2 PS E:docker>


每天喝一杯黄芪水,坚持一个月后,身体会发生怎样的变化?了解下黄芪,作为一种养生的医用药材,有较高的营养价值!黄芪,在神农本草经中就有记载针对于大风癞疾,小儿百病,身体虚弱都有很好的治疗辅助作用。黄芪可谓是中药材中最常见的一味药材,药用价值非微信又上线新功能,网友没必要微信又有新功能啦有小伙伴发现微信升级全新版本后增加了手机温度监控等新功能打开微信后点击我设置找到下方帮助与反馈点击进入进入帮助与反馈后点击右上方的小扳手按钮之后点击性能检测工具进入值得入手的三款12GB256GB手机,可以考虑这三款,轻松用到2026年值得入手的三款12GB256GB手机,可以考虑这三款,能轻松用到2026年第一款摩托罗拉EdgeSPro在影像方面后置三摄,1。08亿像素主摄(三星ISOCELLHM2传感器,11从3699降至2499元?荣耀50Pro曲面屏手机100W快充8GB256GB荣耀手机2020年被华为出售给智信新公司以来,仍然保持着快速的发展,其中去年荣耀50系列线上全平台首销1分钟突破5亿销售额,可见荣耀手机是多么地受消费者欢迎。时隔一年这款荣耀50P物理学家伊曼纽尔德曼开启的量化金融时代今天的华尔街早已不再是那种陈旧的商业模式了。近年来,投资银行和对冲基金已经逐渐转向通过量化交易策略和衍生金融产品来获得利润了,它们招募了大量拥有博士学位的学术精英,这些精英对这些易微信又上新功能!网友一言难尽微信又有新功能啦有小伙伴发现微信升级全新版本后增加了手机温度监控等新功能打开微信后点击我设置找到下方帮助与反馈点击进入进入帮助与反馈后点击右上方的小扳手按钮之后点击性能检测工具进入马斯克收购推特的英语表达ComparedwithitsrivalsFacebook,InstagramandTikTokTwitterisaminnow。Butthedealmatters。同Facebo入选奖金30万!OPPO全球征集科技创新提案,网友这波格局打开了如今科技快速发展,也深入到了每个普通人的美好生活,改变许多人的认知与见识。而就在大家都享受科技便利之时,我们的社会里仍然有这么一部分人难以获得高效的科技服务,因某些局限性而无法触及降房价是个伪命题?这是第4493篇原创首发文章字数3k梁云风文关注秦朔朋友圈IDqspyq2015天下苦房价久矣。4月21日,中国人民大学教授吴晓求在博鳌亚洲论坛媒体见面会上说中国房价太高,让年轻人开盘A股三大指数集体低开沪指跌0。38,基建股逆市活跃,比亚迪跌4。58金融界5月9日消息今日A股三大指数集体低开,沪指跌0。38,报2990。2点,深成指跌0。62,报10743。03点,创业板指跌0。39,报2236。17点盘面上,工程咨询服务工程22年让人惊艳的宝藏好物!路卡ROCARM90系列智能酒精手表品牌好物运动手表智能手表酒精检测随着社会经济快速发展,人们生活水平不断提高,健康意识越来越强,显然已成为手机附属的智能手表,在业内发展中,已从最简单的运动监测到现在的多样化,成为了
五款主流电动小车操控性能大比武,结果可能让你意外如今随着纯电动汽车的逐渐普及,消费者在选购车辆前,往往将关注点都集中在续航里程充电时间等方面,很少提及操控性能。非要聊操控的话,也大多是谈谈直线加速成绩,至于其他操控指标就更少涉及我们996,欧美上4休三3,为啥人家挣钱比我们多头条创作挑战赛当我们还在996007玩命内卷的时候,大洋彼岸已经在试行上4休3了,可是我们的薪资收入,依然远低于欧美平均工资,是我们的企业不够大,还是利润不够多,到底哪里出了问题?同样都在裁员,为什么某度裁员负面新闻最多?今年可以说是互联网行业的裁员年,涉及到的裁员大厂包括百度阿里腾讯美团京东等等。部分公司和员工好聚好散,部分公司和员工成了仇人,要说其中产生最大负面舆论的,莫过于我的前东家某度了。0再度表白女友,克耶高斯今年爆发的原因找到了今年的美网,坏小子克耶高斯不敌卡恰诺夫,无缘四强。但能够在八强战淘汰梅德维德夫,成为夺冠热门,足以看出克耶高斯本届美网的表现。再往前看,今年的温网,克耶高斯首次打入决赛。似乎从今年永劫无间元宇宙终于来了!游戏场景成现实景点,被导游热捧前段时间你这背景太假了这个梗火爆网络,原本是一位来自新疆的网友在直播的时候被质疑,说他的背景很假,而面对大家的打假,他跟背景互动来验证真实性,没想到反而引起大量网友二创,也让这个梗喷一喷小游戏羊了个羊最近又一款非常流行的小游戏羊了个羊,不知怎么就火了,而且还是爆火。带着好奇蹭热闹的心情,我也试着玩了玩,在短暂尝试后旋即退出,下面是我对这个游戏的吐槽。羊了个羊,毫无疑问,就连制作倾住全力为民安居岳阳住房公积金这十年红网时刻岳阳9月20日讯党的十八大以来的这十年,是岳阳住房公积金事业快速发展的十年。管理中心始终牢记习近平总书记关于住房建设工作的一系列新思想,新理念,新战略,倾住全力,为民安居,竞速游戏达喀尔拉力赛国区涨价116元升至159元竞速游戏达喀尔拉力赛(DakarDesertRally)Steam各地区预购价格上涨,国区由116元升至159元。该作将于2022年10月4日发售,不支持中文。达喀尔拉力赛是有史以Splatoon可以是换装游戏,只要你愿意游戏Splatoon(喷射战士)自初代发售,就以极其贴合时下潮流的装备穿搭而出圈,其第三代splatoon3更是获得了超高的关注度和购买量,上线3天就超越了动森成为新晋销量冠军。大在哪里买苹果手机便宜对于全新国行苹果手机的购买渠道,最让人安心的就是官网,除了正常的全新机,官网还出售官翻和官修机,这些机子价格会稍便宜一点,同时质量和售后一样可以得到保障,而且支持14天无理由退换货三星手机为什么是全球第一三星s21ultra背面由于三星s22ultra内置spen,外观尺寸偏大,我又爱惜的不得了,加个手机壳,就更大,不得不换回了s21ultra。但还是喜欢spen的书写体验,不得不