Abstract摘要:

1、Fetch的官方规范文档:https://fetch.spec.whatwg.org/,你可以去官网规范上查看如何使用fetch。

2、Fetch API 提供了一个 JavaScript 接口,优化了http请求和响应的操作方式。这种功能以前是使用 XMLHttpRequest (ajax)实现的。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。

3、fetch最大的特点是与Promise对象的结合,Fetch API大多方法都返回一个Promise对象,使我们的编程风格更加优雅(上流)。我们知道jquery的ajax也实现了Promise功能;还有axios插件,Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

4、学习Fetch我们要搞懂几个知识点:fetch方法、Header对象、Request对象、Response对象等。

fetch的缺点:

兼容性不好的中止请求方法和没有实现的超时处理:无法像XMLHttpRequest那样abort中止请求,以及超时处理timeout。

兼容性:不支持IE,Edge14,Chrome40,Firefox39,Safari10。

Usage使用:

fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。

语法:

fetch(input[, init]);

input:定义要获取的资源,可以是一个url或者一个Request对象

init:可选的,一个配置对象,包含了对请求的设置

下面实例中,是对上述fetch()方法的最好解释。

        var url = "https://mock.yonyoucloud.com/mock/16388/test/cities";fetch(url, {method: "GET",mode: 'cors',cache: 'default'}).then(function(response){return response.json(); //响应内容json化}).then(function(res){console.log(res);  //打印响应值})

fetch方法发起请求,返回一个promise对象,promise对象调用then方法,返回一个Response对象。注意这里返回的是Response对象。

必须调用两次then方法:Response对象的json()方法是对数据的处理,也是一个promise对象。第二个then方法的结果res,正是response.json()该promise对象的处理的结果。


我们还需要了解别的响应数据的格式:

1、Response.json()会将响应流数据读成json格式:


2、而Response.text()会将响应流数据读成text类型:

        var url = "https://mock.yonyoucloud.com/mock/16388/test/cities";var cityRequest = new Request(url);fetch(cityRequest).then(function (response) {response.text().then(function (res) {console.log(res);});})

{"success":true,"data":["北京","上海"]}

注意:

(1)上面代码的写法,我们说过,Response.json()、Response.blob()等都是Promise对象,所以response.text()可以直接调用then方法。 

(2)fetch方法第一个参数也可以接收一个Request。


3、Response.blob()可以将响应流数据读成二进制格式。上述实例的blob()方法输出:

blob方法处理图片,比如处理图片资源,如下:

        var myImage = document.querySelector('img');var myRequest = new Request('https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1819216937,2118754409&fm=26&gp=0.jpg');fetch(myRequest).then(function (response) {response.blob().then(function (myBlob) {var objectURL = URL.createObjectURL(myBlob);console.log(objectURL);myImage.src = objectURL;});});

波及到的知识点,具体分析:

一、fetch的使用

参数1:请求资源;参数2:init配置项:可选参数,一个可以控制不同配置的 init 对象

以一个实例开始:POST请求的实现

        postData('https://mock.yonyoucloud.com/mock/16388/test/post/star', {name: "liu"}).then(data => console.log(data)) // JSON from `response.json()` call.catch(error => console.error(error))function postData(url, data) {// Default options are marked with *return fetch(url, {body: JSON.stringify(data), // must match 'Content-Type' headercache: 'no-cache', // credentials: 'same-origin', //  *omit不带cookie, same-origin同源带cookie, include跨域带cookieheaders: {'content-type': 'application/json' //发送的数据类型},method: 'POST', // *GET, POST, PUT, DELETE, etc.mode: 'cors', // no-cors, cors, *same-originredirect: 'follow', // manual, *follow, errorreferrer: 'no-referrer', // *client, no-referrer}).then(response => response.json()) // parses response to JSON}

init的配置项可以参考:https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch

  • method: 请求使用的方法,如 GET、POST。默认GET
  • headers: 请求的头信息,形式为 Headers 的对象或包含 ByteString 值的对象字面量。比如:headers : { 'Content-Type' : 'application/json' },可以设置所有的header信息。
  • body: 请求的 body 信息:可能是一个 BlobBufferSourceFormDataURLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
  • mode: 请求的模式,如 默认cors跨域 no-cors不跨域 或者 same-origin。
  • credentials: 请求的 credentials,如 默认omit不携带cookiesame-origin同源携带cookie 或者 include跨域携带cookie。但在Chrome中,Chrome 47 之前的版本默认值为 same-origin ,自Chrome 47起,默认值为include。
  • cache:  请求的 cache 模式: default、 no-store不缓存、 reload 、 no-cache有缓存但仍需要去服务器获取资源 、 force-cache 或者 only-if-cached 。
  • redirect: 可用的 redirect 模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在Chrome中默认使用follow(Chrome 47之前的默认值是manual)。
  • referrer: 一个 USVString 可以是 no-referrer、client或一个 URL。默认是 client。
  • referrerPolicy: 指定了HTTP头部referer字段的值。可能为以下值之一: no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。

拓展:结合async和await使用fetch:

        async function asyncFetch (){let response = await fetch('https://mock.yonyoucloud.com/mock/16388/test/cities');let data = await response.json();console.log(data);}asyncFetch()

拓展: 如何中止fetch请求呢?

一个实验中的api,具有abortI方法的AbortController()构造函数。 兼容性,不太良好。IE不兼容,Edge16,Firefox57,Chrome66,Safari12。

以下是取消 fetch 调用的工作流程:

  • 创建一个 AbortController 实例
  • 该实例具有 signal 属性
  • 将 signal 传递给 fetch option 的 signal
  • 调用 AbortController 的 abort 属性来取消所有使用该信号的 fetch。

示例中,发起请求下载视频资源,下载的过程中,中止下载。

fetch方法中的配置项中,添加了新的的配置项,signal

var controller = new AbortController();
var signal = controller.signal;var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');downloadBtn.addEventListener('click', fetchVideo);abortBtn.addEventListener('click', function() {controller.abort();console.log('Download aborted');
});function fetchVideo() {...fetch(url, {signal}).then(function(response) {...}).catch(function(e) {reports.textContent = 'Download error: ' + e.message;})
}

中止请求:controller.abort()方法,

        const controller = new AbortController();const signal = controller.signal;console.log(signal);fetch('https://mock.yonyoucloud.com/mock/16388/test/cities', {signal}).then(function (response) {response.json().then(function (res) {console.log(res);})})controller.abort();//终止请求,但是如何区分各个fetch请求呢?

在 abort 调用时发生 AbortError,上述代码结果如下:一个是signal对象,一个是中止请求成功后报的错误AbortError。

但是怎么区分每个fetch请求呢?每创建的一个controller对象,将controller的signal传入到fetch请求的配置项中,当执行controller.abort()方法时,就会去中止该controller的signal项。

实现一个通用方法:

        function abortableFetch(request, opts = {}) {const controller = new AbortController();const signal = controller.signal;opts.single = signal;return {abort: () => controller.abort(),startFetch: () => fetch(request, opts)};}var abortFetch = abortableFetch('https://mock.yonyoucloud.com/mock/16388/test/cities')abortFetch.startFetch().then(function(response){response.json().then(function(res){console.log(res);})})

参考文章:

https://developer.mozilla.org/zh-CN/docs/Web/API/FetchController/abort

https://segmentfault.com/a/1190000022148239

https://davidwalsh.name/cancel-fetch

拓展:POST请求可以在body中设置参数,GET请求如何设置请求参数呢?

fetch方法的GET请求,不允许设置body。那该如何传参呢?

方法1:拼接url

        var page = 1;var name = "beijing";var url = 'https://mock.yonyoucloud.com/mock/16388/test/cities';var params = '?page=' + page + '&' + 'name=' + name;url = url + params;console.log(url); //https://mock.yonyoucloud.com/mock/16388/test/cities?page=1&name=beijingfetch(url).then(response => response.json().then(res => {console.log(res);}))

方法2:通过该文最后所提到的,额外补充的知识,关于url 的操作,可以使用URLSearchParams构造函数,创建url的拼接参数。 URLSearchParams构造函数的兼容性:Edge17、Firefox29、Chrome49

(1)URLSearchParams构造函数的使用

可接受query字符串参数;也可以接受二维数组,像Map那样。得到的Params对象,调用toString方法,得到query string parameters

        // 创建url对象var url = new URL('https://mock.yonyoucloud.com/mock/16388/test/cities?page=1&name=beijing');var params = new URLSearchParams(url.search); //url.search是查询字符的的内容,"?page=1&name=beijing"// 接收查询字符串的内容var params2 = new URLSearchParams("foo=1&bar=2");var params2a = new URLSearchParams("?foo=1&bar=2");// 接收一个二维数据var params3 = new URLSearchParams([["foo", "1"],["bar", "2"]]);// 接收一个json对象var params4 = new URLSearchParams({"foo": "1","bar": "2"});console.log(params.toString());  //page=1&name=beijingconsole.log(params2.toString()); //foo=1&bar=2console.log(params2a.toString()); //foo=1&bar=2console.log(params3.toString());// foo=1&bar=2console.log(params4.toString()); //foo=1&bar=2

(2)所以可以这么用:

        var page = 1, name = 'beijing';// 接收一个json对象var params = new URLSearchParams({"page": page,"name": name});url = url + '?' + params.toString();console.log(url); //https://mock.yonyoucloud.com/mock/16388/test/cities?page=1&name=beijing

二、Request对象

我们可以通过Request构造函数, 构造一个Request对象,而fetch的第一个参数可以接受Request对象。

语法:var myRequest = new Request(input[, init]);

参数:

input

定义你想要fetch的资源。可以是下面两者之一:

  • 一个直接包含你希望 fetch 的资源的 URL 的 USVString
  • 一个 Request 对象。请注意以下行为更新,以在保留安全性的同时使构造函数不太可能引发异常:
    • 如果此对象存在于构造函数调用的另一个起源上,则将除去Request.referrer
    • 如果此对象的导航为 Request.mode,则mode将转换为same-origin

init 可选

一个可选对象,包含希望被包括到请求中的各种自定义选项。可用的选项如下:

  • method: 请求的方法,例如:GETPOST。
  • headers: 任何你想加到请求中的头,其被放在Headers对象或内部值为ByteString 的对象字面量中。
  • body: 任何你想加到请求中的body,可以是BlobBufferSourceFormDataURLSearchParams, 或 USVString对象。注意GET 和 HEAD请求没有body。
  • mode: 请求的模式, 比如 corsno-corssame-origin, 或 navigate。默认值为 cors
  • credentials: 想要在请求中使用的credentials:: omitsame-origin, 或 include。默认值应该为omit。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为 same-origin。Firefox 也在 61.0b13 版本中进行了修改)。但在Chrome中,Chrome 47 之前的版本默认值为 same-origin ,自Chrome 47起,默认值为include。
  • cache: 请求中想要使用的 cache mode
  • redirect: 对重定向处理的模式: followerror, or manual。在Chrome中,Chrome 47 之前的版本默认值为 manual ,自Chrome 47起,默认值为follow。
  • referrer: 一个指定了no-referrerclient, 或一个 URL的 USVString 。默认值是about:client
  • integrity: 包括请求的 subresource integrity 值 (e.g., sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=).
        var myRequest = new Request('https://mock.yonyoucloud.com/mock/16388/test/cities',{method: 'GET',headers: {'Content-Type': 'application/json'},mode: 'cors' })fetch(myRequest).then(function(response){response.json().then(function(res){console.log(res);})})

三、Response对象

当fetch()方法执行结束时,会返回一个Response对象,我们可以通过Response对象的属性和方法来查看相关响应信息。Response对象的方法来处理response响应,比如json()、text()、blob()等方法。

Response.headers  值 对象, 只读 ,包含该Response所关联的Headers对象

Response.ok 值true ,只读,包含了一个布尔值,表示该Response是否成功(状态码在200-299的为true)

Response.status  值200 ,只读,该Response状态码,200表示成功。404表示服务器没有该资源。

Response.statusText  值OK, 只读,表示与status状态码一直的信息,200 对应 OK

Response.url   值是一个url地址,只读,表示该Response的url

Response.redirected  只读,表示该 Response 是否来自一个重定向,如果是的话,它的 URL 列表将会有多个条目。

Response.type  响应类型,只读,包含 Response 的类型(例如,basiccors)。

Response.body  一个简单的 getter,表示 body 内容。

几个方法:Response实现了Body接口,所以可以使用以下方法:

Body.json() 读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 JSON 格式的 Promise 对象。

Body.text()读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 USVString 格式(文本格式)的 Promise 对象。

Body.blob()读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 Blob 格式(二进制格式,包含二进制数据信息)的 Promise 对象。

Body.formData()读取Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 FormData 格式的 Promise 对象。

Body.arrayBuffer()读取 Response 对象并且将它设置为已读(因为 Responses 对象被设置为了 stream 的方式,所以它们只能被读取一次),并返回一个被解析为 ArrayBuffer 格式的 Promise 对象。


四、Headers对象

Headers 接口允许您对HTTP请求和响应头执行各种操作。 这些操作包括检索,设置,添加和删除。

一个Headers对象具有关联的头列表,它最初为空,由零个或多个键值对组成。

在该接口的所有方法中,标题名称由不区分大小写的字节序列匹配。

出于安全考虑,某些头只能由用户代理控制。这些头信息包括 forbidden header names  和 forbidden response header names。

————简单的说:Headers对象就是设置请求头headers的。

Headers对象的方法:

Headers.append()方法:给现有的header添加值。

Headers.delete()方法,删除现有header的某个值。

Headers.get()方法,获取现有header的某个值。

Headers.has()方法,判断现有header中是否有某个值。

使用:用于fetch方法的配置项中的headers

let myHeaders = new Headers(); //创建一个header空对象。
myHeaders.append('Content-Type', 'text/xml');console.log(myHeaders.get('Content-Type'));  // should return 'text/xml
console.log(myHeaders.has('content-type')); //true ,不区分大小写fetch('https://mock.yonyoucloud.com/mock/16388/test/cities', {headers: myHeaders
}).then(response => response.json().then(res => {console.log(res);
}))

比如获取图片:

var myImage = document.querySelector('img');var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');var myInit = { method: 'GET',headers: myHeaders,mode: 'cors',cache: 'default' };var myRequest = new Request('flowers.jpg');fetch(myRequest,myInit).then(function(response) {...
});

五、Blob对象

Blob对象代表响应/请求的正文,允许你声明其内容类型是什么以及应该如何处理。Body被Request和Response实现(Request中的body、Response中的body),并为这些对象提供了一个相关联的主体(字节流),一个已使用的标志(最初未设置)和一个MIME类型(最初为空字节序列)。

Body.body属性(被Request和Response实现了该属性),一个简单的getter,用于获取主体内容。

Body的方法,如上所述。

六、fetch、jquery的ajax、axios的区别

fetch 规范与 jQuery.ajax() 主要有三种方式的不同:

  • 当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。——404 或500 状态码的处理,fetch会返回resolve,而jquery.ajax返回reject。
  • 关于cookie,规范由默认不带,该为默认同源带cookie;Chrome由默认同源带cookie,改为跨域也带cookie。

1、原生ajax的实现:

五步骤:

1)创建XmlHttpRequest对象
2)调用open方法设置基本请求信息
3)设置发送的数据,发送请求
4)注册监听的回调函数
5)拿到返回值,对页面进行更新

//1.创建Ajax对象if(window.XMLHttpRequest){var oAjax=new XMLHttpRequest();}else{var oAjax=new ActiveXObject("Microsoft.XMLHTTP");}//2.连接服务器(打开和服务器的连接)oAjax.open('GET', url, true);//3.发送oAjax.send();//4.接收oAjax.onreadystatechange=function (){if(oAjax.readyState==4){if(oAjax.status==200){//alert('成功了:'+oAjax.responseText);fnSucc(oAjax.responseText);}else{//alert('失败了');if(fnFaild){fnFaild();}}}};

在ES6的基础上,通过XMLHttpRequest对象和Promise、async、await来实现一个fetch:

参考文章:https://www.jianshu.com/p/7762515f8d1a

2、$.ajax()的使用:

        $.ajax({url: "https://mock.yonyoucloud.com/mock/16388/test/cities",type: 'GET',data: {},success: function(res){console.log(res);},timeout: 5000, //超时设置dataType: 'json', //预期服务器响应的内容类型。cache: true, //默认值true,缓存contentType: 'application/x-www-form-urlencoded', //默认值 发送数据到服务器时所使用的内容类型。beforeSend: function(){ //发送前运行的函数}})

jquery中ajax的promise使用:

        $.get('https://mock.yonyoucloud.com/mock/16388/test/cities').then(function(res){console.log(res);return $.get('https://mock.yonyoucloud.com/mock/16388/test/movies')}).then(function(res){console.log(res);}).catch(function(err){console.log(err);})

3、axios的使用

axios官网:http://www.axios-js.com/

具体的使用还需要深入研究。。。


4、GitHub上的fetchpollfill

地址:https://github.com/github/fetch

该pollfill的支持情况:Browser Support:

  • Chrome
  • Firefox
  • Safari 6.1+
  • Internet Explorer 10+

具体的使用,还需要深入研究。。。


额外,关于url的操作:

1、URL.createObjectURL() 创建一个url

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

语法:objectURL = URL.createObjectURL(object);

参数object:用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。​

上面例子中,使用的Blob对象。

参考文章:

https://developer.mozilla.org/zh-CN/docs/Web/API/URL/createObjectURL

https://developer.mozilla.org/zh-CN/docs/Web/API/File/Using_files_from_web_applications#Example.3A_Using_object_URLs_to_display_images

2、URLSearchParams.toString

接口的toString() 方法URLSearchParams返回适合在URL中使用的查询字符串。——此方法返回不带问号的查询字符串

语法: URLSearchParams.toString()

URL构造函数:兼容性:ES6,Edge12

        let url = new URL('https://example.com?foo=1&bar=2');console.log(url);

查看结果:拥有所有关于url的信息。

关于url的参数的一些操作:

        let url = new URL('https://example.com?foo=1&bar=2');console.log(url);let params = new URLSearchParams(url.search.slice(1)); //url.search = ?foo=1&bar=2console.log(params); //URLSearchParams对象//Add a second foo parameter.params.append('foo', 4); //URLSearchParams对象的append方法,添加新的键值对。console.log(params.toString());  //取值:Prints 'foo=1&bar=2&foo=4'

参考文章:https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/toString


参考文章:

https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API

https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch

https://stackoverflow.com/questions/35038857/setting-query-string-using-fetch-get-request?r=SearchResults

Fetch的理解和使用相关推荐

  1. fetch请求理解和用法

    fetch请求 fetch请求使用ES6新增语法–Promise:Promise是一个对象,从它可以获取异步操作的消息,原型上有then.catch等方法,可以对结果进行链式调用而不是用传统的回调函数 ...

  2. 网络传输(个人整理 多网站)

    网络传输 留一个问题:浏览器是怎么解析同源的? js脚本的同源判断 document.domain(浏览器基础安全策略) 脚手架代理的同端口webpack请求代理实现? 跨域以及解决跨域的方法(常规) ...

  3. Git 本地与远程仓库同步操作

    git fetch 做了些什么 git fetch 完成了仅有的但是很重要的两步: 从远程仓库 下载 本地仓库中缺失的 提交记录 更新远程分支指针(假设为 o/master) git fetch 实际 ...

  4. Learn Git Branching 记录

    Learning Git Branching 可以说是目前为止最好的教程了,地址 点击右下角问号显示常用命令 1.提交 git commit 提交内容,并把这些修改保存成了一个提交记录 C3,C3 的 ...

  5. Git入门指南【超详细】

    Git 1. Git简介 Git是分布式版本控制系统(distributed version control system,简称DVCS),分为本地仓库和远程仓库 2. Git工作流程 clone与p ...

  6. Git Learning 学习笔记

    文章目录 1. 前言 2. 基础篇 2.1 Git Commit 2.2 Git Branch 2.3 Git Merge 2.4 Git Rebase 3. 高级篇 3.1 分离HEAD 3.2 相 ...

  7. 理解Git的设计思想,详解git文件夹,以及详解add、commit、push,fetch、pull、merge指令

    在项目目录执行git init,此目录将纳入git管理,git将会自动生成.git文件夹,用以记录git配置(.git/config)和版本信息(commit-id)和文件集合.下面是.git文件夹的 ...

  8. 真正理解 git fetch, git pull 以及 FETCH_HEAD

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 真正理解 git fetch, git pull 要讲清楚git fetch,git pull,必须 ...

  9. 理解git fetch, git pull 以及 FETCH_HEAD的含义

    理解 git fetch, git pull 1. [git remote]首先, git是一个分布式的结构,这意味着本地和远程是一个相对的名称. 本地的repo仓库要与远程的repo配合完成版本对应 ...

最新文章

  1. 数据库jdbc property文件配置信息片段
  2. LeetCode Sort List(单链表归并排序)
  3. MySQL数据库:范式
  4. 金蝶软件怎么过账_代理记账用什么财务软件?
  5. java分层窗格_java 简洁的分层实现
  6. P2P之UDP穿透NAT的原理与实现
  7. C++递归或非递归实现n的阶乘
  8. oracle数据库常用操作语句
  9. poj 1077 Eight(bfs,dbfs, A*)
  10. android qq卡屏代码,2015最新卡死安卓QQ代码 卡到让对方手机QQ无响应及代码分享...
  11. 数学分析教程(科大)——4.3笔记+习题
  12. 持久内存服务器大多数数据库管理系统,内存数据库VS传统数据库:如何在多个任务之间共享内存中的数据?...
  13. EXCEL中如何分段进行快速填充
  14. 深度测评小程序跨端开发框架
  15. 动态规划:区间动态规划
  16. 【计算智能】模糊控制(一)模糊集合及其基本运算
  17. siteservercms 缺点_Siteserver CMS 远程模板下载Getshell漏洞
  18. 自己动手做网络爬虫系列——1
  19. C语言-判断是不是字母
  20. Qt操作excel基本方法

热门文章

  1. Linux虚拟机连接网络,CentOS的联网技巧
  2. Firebug工具 —— 简单学习一下测试
  3. Lava为什么可以在PoC项目中脱颖而出
  4. 电商搜索引擎实践(工程篇)
  5. FPC软板设计和FR-4有什么不一样?
  6. 6+66+666+...+666...666的前n项和
  7. WebService CXF系列: SpringBoot同一个项目中集成JaxWS和JaxRS
  8. 报错:Type mismatch: cannot convert from Object to Car
  9. 山西初中计算机网络教案,山西省各地初中教材版本
  10. [hiho 13]最近公共祖先 一