4.1 Ajax & APIs
一定要看这个视频:Youtube: Client Server Demonstration - Intro to AJAX
生动形象地解释了:
- 同步情况下工作机制:client、server、request、response
- 异步情况下工作机制:ajax、callback、response
- 为什么要使用异步请求:减少了同步模式下,等待 response 的时间。callback 是用来后续处理的 instructor,不必等待以后,时间可以都拿来做其他有用的事,比如渲染其他内容
了解了基本概念后,我们只需要从下面三个方面来学习 ajax,并最快地投入工业实践中去:
- 发送网络请求的几种方法:
jQuery.ajax()
、fetch()
、axios
等 - 处理异步请求的几种方法:callback、promise、async/await
- 刻意练习
发送网络请求
$.ajax()
- 文档:http://api.jquery.com/jquery.ajax/
- 综述性文章:http://adaptivepath.org/ideas/ajax-new-approach-web-applications/
目前用着觉得 jQuery 的 ajax 可定制性是最好的。只不过代码会相对长一些,但可自动化程度高。但突然,我发现了一个更好的选择:axios。不仅有良好的 API、全端支持、默认配备 Promise,并且库的大小比 jQuery 小很多(10.3KB : 93.8KB)。如果项目原来并没有在用 jQuery,或者就是一个后端项目的话,我会使用 axios。当然,团队选型是另一回事。
axios
axios 是一个优秀的 ajax 请求发送库,是我目前的选型。理由如下:浏览器端+服务器端的支持,默认支持 promise,良好的 API 设计(支持 get 参数对象配置),灵活的 HTTP 请求配置(header、cookie、interceptor 等配置)。并且,由于专注,它的库体积比 jQuery 要小很多(10.3KB : 93.8KB)。如果是纯后端的项目,或者原来项目并未已有 jQuery 存在,axios 是不错的选择。
fetch()
简洁的 API。配合 promise、await/async 服用,优雅无比。不过这东西神坑,就说对于最简单的 API GET 请求,它不支持 query parameter 参数的选项,非得让你用个库或者自己写个方法把它拼到 URL 后面去。用户体验极差。其他缺陷 这个 issue 讲了,不赘述。另外注意,fetch
是依赖于 promise 的 API,所以可能你还要处理 promise 相关的内容,请见下面章节。
- 规范:https://fetch.spec.whatwg.org/
- 综述性文章:传统 Ajax 已死,Fetch 永生 camsong/blog#2
- 综述性文章:http://wwsun.github.io/posts/fetch-api-intro.html
这个 API 是各大浏览器各自支持的。说到浏览器,就必然有「不同浏览器兼容(定制实现)」、「旧版本浏览器没有支持」、「服务端支持情况」三个问题。前两者(API 兼容与缺失)可以通过著名的 polyfill 库来解决;后者通过「专门的服务端库」或「同构库」来解决。
- 浏览器端 API 兼容 polyfill:https://github.com/github/fetch
- 浏览器端 API 缺失 polyfill(IE-8):https://github.com/camsong/fetch-ie8
- 服务器端 fetch:https://github.com/bitinn/node-fetch
- 同构 fetch:https://github.com/matthew-andrews/isomorphic-fetch
其他工具
什么区别?怎么确定用哪个呢?这要看你的需求。大致的衡量指标有:
- 是否支持 Promise /
await/async
。比如 request 模块就需要 wrapper 才能支持 promise,那对于需要 promise 的项目来说就要慎用 - 浏览器端、服务器端、polyfill 等的支持情况如何。request 只能用于 node 端;
- API 是否简洁。会不会跟
fetch
一样,连个 query parameter 都要手写? - HTTP 相关功能支持是否完善,比如 header intercept、请求能否中断、能否自传入 header/cookie、认证方式支持(如 JSONP、CORS)等
总的来说,request 对全端支持也不好,promise 支持也没有,基本弃用;直观感受来看,superagent 的 API 不够简洁,但项目有机会的话可以试用。
上面是前言。还好我做了自己的小思考和小考察,要不然,看到下面这哥们的图我一定直接抄过来得了:
http://andrewhfarmer.com/ajax-libraries/ 。
处理异步请求
回调没什么好说的。
Promise
- 官方规范:https://promisesaplus.com/
- MDN 介绍:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
- 综述性文章:https://developers.google.com/web/fundamentals/getting-started/primers/promises
- 各浏览器、nodejs 端支持情况:
基本上 Node 4+以后的版本都原生支持 Promise 了,但如果不幸你在使用更低的版本,那么你可能需要一个 polyfill:https://github.com/stefanpenner/es6-promise 。
另外,虽然有一个规范在那里,但是浏览器之间可能支持情况不同,或是有自己的定制实现,或是低版本浏览器不兼容 promise 规范等。如有此种情况,可在浏览器端使用 polyfill:https://github.com/taylorhakes/promise-polyfill 。
promise 比回调高了一个抽象层次,但依然不是线性的思维。这是唯一一个缺点。把非线性思维变成线性,便来到我们终极的解决方案:await/async。
ES7 await/async
await / async 是基于 Promise 的。所以说,只要 API 支持标准 promise 规范的返回,它就可以通过 ES7 的 babel 被转译成支持 await/async
的代码。
How to Ajax
可选工具库
$.ajax()
axios
client 端可以使用 $.ajax
;nodejs 端可以使用 axios
。API 都比较简洁,都支持简单的 GET 请求及参数组装,axios 支持 promise,jQuery 有自带的回调机制。fetch
简洁到极致,但还需要观望一下,它不支持 GET 请求的参数拼装。为简便故,选此两库作为练习。
通用套路
一定要刻意练习至几度熟练。编程能力提高核心就都在这了。
- 准备必须的(required)数据
- url。坑点在于,一般必须打开网页去找去看,了解哪些参数是必须的,可传何值。这个时间进程与 API 文档好坏大有关系
- query params
- api key:如果不通过复杂的 OAuth 验证等,一般你需要注册一个开发者 key 然后才能调到 API
- query string:一般应该至少有个要查询的内容吧。除非你是要对方把所有的资源一口气返回
- 其他
- 准备 optional settings 数据
method: 'GET'
。这个可以配置成 default,省去配置dataType: 'json'
。这个一般请求库也会默认帮你这么处理,省去配置
- 调用 ajax 库,发送 ajax 请求
- 拿到 response 数据,拿到形式与所用库的 API 设计有关系
- ES6 promise
- ES7
await/async
- 成功处理
- jQuery 应用:确定要展示数据及内容;更新对应的 DOM 结构;编写样式;改变对应 CSS 以应用样式
- 双向绑定框架:把数据变化更新到 Model 或发出 action;编写样式;实现 class toggle 逻辑以应用样式
- 失败处理
需要培养的意识或 debug 能力::
- API 写出来后,亲手调一下看有没有返回数据。若有,证明 url 正确,请求发送成功,数据被正确接收
- 收到数据后,直接在浏览器将 json 可视化出来,数据结构一目了然。利于上面第5步确定需要取到数据
上面虽然这么多步骤,但需要你提供的其实只是一个 url
,apikey
,以及其他可选参数,其他都是 API 调用结构的骨架代码。因此,编写一个 live template,可以最大程度地减少重复工作:
APIs
API 是 Ajax 的延续。Ajax 调的服务哪里来呢?你可以是自己写,自己提供;也可以使用别人提供的服务。这些服务就是狭义上的 API。
SOP(Same-Origin Policy), CORS, JSONP and CSP(Content Security Policy)
有 Ajax 的地方就有 API,有三方 API 和浏览器的地方就有 SOP。那么,什么是 SOP?为什么要有这个东西? 为什么只在浏览器上有?没有会怎么死?作为 API 提供方,我有没有办法禁止某些服务器端的访问?SOP 问题我们又如何正当地解决呢?作为解决方案的 JSONP / CORS / CSP,它们是如何解决的呢?特定场景下的推荐方案是什么呢?
- https://www.wikiwand.com/en/Same-origin_policy
- http://www.ruanyifeng.com/blog/2016/04/cors.html
- https://www.html5rocks.com/en/tutorials/cors/
- https://blog.coding.net/blog/spring-mvc-cors
- http://www.ruanyifeng.com/blog/2016/09/csp.html
- http://stackoverflow.com/questions/39488241/what-is-the-difference-between-cors-and-csps
- http://stackoverflow.com/questions/22977849/securing-application-against-xss/22983608#22983608
- http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/
const apiKey = '$API_KEY
APIs
API 是 Ajax 的延续。Ajax 调的服务哪里来呢?你可以是自己写,自己提供;也可以使用别人提供的服务。这些服务就是狭义上的 API。
SOP(Same-Origin Policy), CORS, JSONP and CSP(Content Security Policy)
有 Ajax 的地方就有 API,有三方 API 和浏览器的地方就有 SOP。那么,什么是 SOP?为什么要有这个东西? 为什么只在浏览器上有?没有会怎么死?作为 API 提供方,我有没有办法禁止某些服务器端的访问?SOP 问题我们又如何正当地解决呢?作为解决方案的 JSONP / CORS / CSP,它们是如何解决的呢?特定场景下的推荐方案是什么呢?
- https://www.wikiwand.com/en/Same-origin_policy
- http://www.ruanyifeng.com/blog/2016/04/cors.html
- https://www.html5rocks.com/en/tutorials/cors/
- https://blog.coding.net/blog/spring-mvc-cors
- http://www.ruanyifeng.com/blog/2016/09/csp.html
- http://stackoverflow.com/questions/39488241/what-is-the-difference-between-cors-and-csps
- http://stackoverflow.com/questions/22977849/securing-application-against-xss/22983608#22983608
- http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/
const queries = $.param({}) const parameters = { 'api-key': apiKey, q: queries } const settings = { method: 'GET', dataType: 'json' } const endpoint = `${url}?${params}` console.log(endpoint) $.ajax(endpoint, settings).done(data => { console.log(data) }).fail(error => { console.log(error) })
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论