4.1 Ajax & APIs

发布于 2022-04-20 12:34:46 字数 13897 浏览 992 评论 0

一定要看这个视频:Youtube: Client Server Demonstration - Intro to AJAX

image

生动形象地解释了:

  • 同步情况下工作机制:client、server、request、response
  • 异步情况下工作机制:ajaxcallback、response
  • 为什么要使用异步请求:减少了同步模式下,等待 response 的时间。callback 是用来后续处理的 instructor,不必等待以后,时间可以都拿来做其他有用的事,比如渲染其他内容

了解了基本概念后,我们只需要从下面三个方面来学习 ajax,并最快地投入工业实践中去:

  • 发送网络请求的几种方法:jQuery.ajax()fetch()axios
  • 处理异步请求的几种方法:callback、promise、async/await
  • 刻意练习

发送网络请求

$.ajax()

目前用着觉得 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 相关的内容,请见下面章节。

这个 API 是各大浏览器各自支持的。说到浏览器,就必然有「不同浏览器兼容(定制实现)」、「旧版本浏览器没有支持」、「服务端支持情况」三个问题。前两者(API 兼容与缺失)可以通过著名的 polyfill 库来解决;后者通过「专门的服务端库」或「同构库」来解决。

其他工具

什么区别?怎么确定用哪个呢?这要看你的需求。大致的衡量指标有:

  • 是否支持 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/

image

处理异步请求

回调没什么好说的。

Promise

基本上 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 请求的参数拼装。为简便故,选此两库作为练习。

通用套路

一定要刻意练习至几度熟练。编程能力提高核心就都在这了。

  1. 准备必须的(required)数据
    • url。坑点在于,一般必须打开网页去找去看,了解哪些参数是必须的,可传何值。这个时间进程与 API 文档好坏大有关系
    • query params
      • api key:如果不通过复杂的 OAuth 验证等,一般你需要注册一个开发者 key 然后才能调到 API
      • query string:一般应该至少有个要查询的内容吧。除非你是要对方把所有的资源一口气返回
      • 其他
  2. 准备 optional settings 数据
    • method: 'GET'。这个可以配置成 default,省去配置
    • dataType: 'json'。这个一般请求库也会默认帮你这么处理,省去配置
  3. 调用 ajax 库,发送 ajax 请求
  4. 拿到 response 数据,拿到形式与所用库的 API 设计有关系
    • ES6 promise
    • ES7 await/async
  5. 成功处理
    • jQuery 应用:确定要展示数据及内容;更新对应的 DOM 结构;编写样式;改变对应 CSS 以应用样式
    • 双向绑定框架:把数据变化更新到 Model 或发出 action;编写样式;实现 class toggle 逻辑以应用样式
  6. 失败处理

需要培养的意识或 debug 能力:

  1. API 写出来后,亲手调一下看有没有返回数据。若有,证明 url 正确,请求发送成功,数据被正确接收
  2. 收到数据后,直接在浏览器将 json 可视化出来,数据结构一目了然。利于上面第5步确定需要取到数据

上面虽然这么多步骤,但需要你提供的其实只是一个 urlapikey,以及其他可选参数,其他都是 API 调用结构的骨架代码。因此,编写一个 live template,可以最大程度地减少重复工作:

practice-ajax-1

practice-ajax-2

APIs

API 是 Ajax 的延续。Ajax 调的服务哪里来呢?你可以是自己写,自己提供;也可以使用别人提供的服务。这些服务就是狭义上的 API。

image

SOP(Same-Origin Policy), CORS, JSONP and CSP(Content Security Policy)

有 Ajax 的地方就有 API,有三方 API 和浏览器的地方就有 SOP。那么,什么是 SOP?为什么要有这个东西? 为什么只在浏览器上有?没有会怎么死?作为 API 提供方,我有没有办法禁止某些服务器端的访问?SOP 问题我们又如何正当地解决呢?作为解决方案的 JSONP / CORS / CSP,它们是如何解决的呢?特定场景下的推荐方案是什么呢?

const apiKey = '$API_KEY

practice-ajax-1

practice-ajax-2

APIs

API 是 Ajax 的延续。Ajax 调的服务哪里来呢?你可以是自己写,自己提供;也可以使用别人提供的服务。这些服务就是狭义上的 API。

image

SOP(Same-Origin Policy), CORS, JSONP and CSP(Content Security Policy)

有 Ajax 的地方就有 API,有三方 API 和浏览器的地方就有 SOP。那么,什么是 SOP?为什么要有这个东西? 为什么只在浏览器上有?没有会怎么死?作为 API 提供方,我有没有办法禁止某些服务器端的访问?SOP 问题我们又如何正当地解决呢?作为解决方案的 JSONP / CORS / CSP,它们是如何解决的呢?特定场景下的推荐方案是什么呢?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

醉城メ夜风

文章 0 评论 0

远昼

文章 0 评论 0

平生欢

文章 0 评论 0

微凉

文章 0 评论 0

Honwey

文章 0 评论 0

qq_ikhFfg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文