Web API 简介

首先,我们将从宏观层面审视 API:它们是什么,如何工作,如何在代码中使用它们,以及它们的结构是怎样的?我们还将了解不同主要类别的 API 是什么,以及它们有哪些用途。

预备知识 熟悉 HTMLCSSJavaScript,尤其是 JavaScript 对象基础知识以及 DOM 脚本网络请求等核心 API 知识。
学习成果
  • Web API 是什么,以及它们能做什么。
  • API 的使用方式。

API 是什么?

应用程序编程接口(API)是编程语言中提供的构造,旨在让开发人员更轻松地创建复杂功能。它们将更复杂的代码抽象出来,提供了更简单的语法供您使用。

举一个现实世界的例子,想想您家里、公寓或其他住所的电力供应。如果您想在家里使用电器,只需将其插入插座即可工作。您不会尝试将其直接连接到电源——这样做效率非常低,而且如果您不是电工,尝试这样做既困难又危险。

Two multi-plug holders are plugged into two different plug outlet sockets. Each multi-plug holder has a plug slot on it's top and to it's front side. Two plugs are plugged into each multi-plug holder.

图片来源:过载的插座,由 The Clear Communication People 发布在 Flickr 上。

同理,如果您想编程一些 3D 图形,使用 JavaScript 或 Python 等高级语言编写的 API 会容易得多,而不是尝试直接编写控制计算机 GPU 或其他图形功能的低级代码(例如 C 或 C++)。

注意:另请参阅 API 词汇表条目以获取进一步说明。

客户端 JavaScript 中的 API

尤其是客户端 JavaScript,拥有许多可用的 API——它们不属于 JavaScript 语言本身,而是构建在核心 JavaScript 语言之上,为您的 JavaScript 代码提供了额外的超能力。它们通常分为两类:

  • 浏览器 API 内置在您的 Web 浏览器中,能够公开来自浏览器及周围计算机环境的数据,并用它做有用的复杂事情。例如,Web 音频 API 提供了用于在浏览器中操作音频的 JavaScript 构造——获取音轨、改变其音量、应用效果等。在后台,浏览器实际上正在使用一些复杂的低级代码(例如 C++ 或 Rust)来执行实际的音频处理。但同样,这种复杂性被 API 抽象掉了。
  • 第三方 API 默认不内置在浏览器中,您通常需要从 Web 上的某个地方检索它们的代码和信息。例如,Google Maps API 允许您在您的网站上显示办公室的交互式地图。它提供了一组特殊的构造,您可以用来查询 Google Maps 服务并返回特定信息。

A screenshot of the browser with the home page of firefox browser open. There are APIs built into the browser by default. Third party APIs are not built into the browser by default. Their code and information has to be retrieved from somewhere on the web to utilize them.

JavaScript、API 和其他 JavaScript 工具之间的关系

上面我们讨论了客户端 JavaScript API 是什么,以及它们与 JavaScript 语言的关系。让我们回顾一下,使其更清晰,并提及其他 JavaScript 工具的适用位置:

  • JavaScript — 一种内置于浏览器的高级脚本语言,允许您在网页/应用程序中实现功能。请注意,JavaScript 也可在其他编程环境中使用,例如 Node
  • 浏览器 API — 内置于浏览器中,位于 JavaScript 语言之上,让您更轻松地实现功能。
  • 第三方 API — 内置于第三方平台(例如 Disqus、Facebook)中的构造,允许您在自己的网页中使用这些平台的一些功能(例如,在网页上显示您的 Disqus 评论)。
  • JavaScript 库 — 通常是一个或多个 JavaScript 文件,包含您可以附加到网页的自定义函数,以加快或实现常见功能的编写。示例包括 jQuery、Mootools 和 React。
  • JavaScript 框架 — 比库更进一步,JavaScript 框架(例如 Angular 和 Ember)通常是 HTML、CSS、JavaScript 和其他技术的集合包,您安装后可用于从头开始编写整个 Web 应用程序。库和框架之间的关键区别在于“控制反转”。调用库中的方法时,开发人员拥有控制权。而使用框架时,控制权是反转的:框架调用开发人员的代码。

API 能做什么?

现代浏览器中有大量的 API 可用,允许您在代码中执行各种各样的事情。您可以查看 MDN API 索引页面来了解。

常见浏览器 API

特别是,您将使用(并且我们将在本模块中更详细介绍)最常见的浏览器 API 类别是:

  • 用于操作加载到浏览器中的文档的 API。最明显的例子是 DOM(文档对象模型)API,它允许您操作 HTML 和 CSS——创建、删除和更改 HTML,动态地将新样式应用于您的页面等。例如,每次您看到页面上弹出窗口或显示新内容时,那就是 DOM 在发挥作用。在 DOM 脚本简介中了解更多关于这些类型的 API 的信息。
  • 从服务器获取数据以自行更新网页小部分的 API 非常常用。这个看似微小的细节对网站的性能和行为产生了巨大影响——如果您只需要即时更新股票列表或可用新闻故事列表,而无需从服务器重新加载整个页面,这会让网站或应用程序感觉更具响应性和“敏捷”。用于此的主要 API 是 Fetch API,尽管旧代码可能仍使用 XMLHttpRequest API。您可能还会遇到 AJAX 一词,它描述了这种技术。在 使用 JavaScript 发送网络请求中了解更多关于此类 API 的信息。
  • 用于绘制和操作图形的 API 在浏览器中得到广泛支持——最受欢迎的是 CanvasWebGL,它们允许您以编程方式更新 HTML <canvas> 元素中包含的像素数据,以创建 2D 和 3D 场景。例如,您可以使用 Canvas API 绘制矩形或圆形等形状,将图像导入画布并对其应用诸如棕褐色或灰度等滤镜,或者使用 WebGL 创建具有光照和纹理的复杂 3D 场景。此类 API 通常与用于创建动画循环的 API(例如 window.requestAnimationFrame())及其他 API 结合使用,以制作像卡通和游戏那样不断更新的场景。
  • 音频和视频 API,如 HTMLMediaElementWeb Audio APIWebRTC,允许您通过多媒体做一些非常有趣的事情,例如为播放音频和视频创建自定义 UI 控件,在视频中显示字幕和副标题等文本轨道,从网络摄像头获取视频以通过画布(见上文)进行操作或在网络会议中显示给其他人的计算机,或向音轨添加效果(例如增益、失真、声像等)。
  • 设备 API 允许您与设备硬件交互:例如,使用 地理定位 API 访问设备 GPS 以查找用户位置。
  • 客户端存储 API 使您能够将数据存储在客户端,因此您可以创建一个应用程序,在页面加载之间保存其状态,甚至可以在设备离线时工作。有多种选项可用,例如使用 Web Storage API 进行简单的名称/值存储,以及使用 IndexedDB API 进行更复杂的数据库存储。

常见第三方 API

第三方 API 种类繁多;其中一些您迟早可能会用到的更受欢迎的有:

  • 地图 API,例如 MapquestGoogle Maps API,它们允许您在网页上处理各种地图相关事务。
  • Facebook API 套件,它使您能够利用 Facebook 生态系统的各个部分来造福您的应用程序,例如通过 Facebook 登录提供应用程序登录、接受应用内支付、推出有针对性的广告活动等。
  • Telegram API,它除了支持机器人之外,还允许您将 Telegram 频道的内容嵌入到您的网站中。
  • YouTube API,它允许您在您的网站上嵌入 YouTube 视频、搜索 YouTube、创建播放列表等等。
  • Pinterest API,它提供了管理 Pinterest 看板和图钉的工具,以便将它们包含在您的网站中。
  • Twilio API,它提供了一个框架,用于在您的应用程序中构建语音和视频通话功能,从您的应用程序发送 SMS/MMS 等。
  • Disqus API,它提供了一个可以集成到您网站的评论平台。
  • Mastodon API,它使您能够以编程方式操纵 Mastodon 社交网络的功能。
  • IFTTT API,它能够通过一个平台集成多个 API。

API 如何工作?

不同的 JavaScript API 的工作方式略有不同,但通常它们具有共同的特性和相似的工作主题。

它们基于对象

您的代码使用一个或多个 JavaScript 对象与 API 交互,这些对象充当 API 使用的数据(包含在对象属性中)和 API 提供的功能(包含在对象方法中)的容器。

注意:如果您还不熟悉对象的工作原理,您应该返回并完成我们的 JavaScript 对象模块,然后再继续。

让我们回到 Web 音频 API 的例子——这是一个相当复杂的 API,由许多对象组成。最明显的有:

  • AudioContext,它代表一个可以用于操纵在浏览器中播放的音频的音频图,并拥有许多可用于操纵该音频的方法和属性。
  • MediaElementAudioSourceNode,它代表一个包含您希望在音频上下文中播放和操纵的声音的 <audio> 元素。
  • AudioDestinationNode,它代表音频的目的地,即您的计算机上实际输出音频的设备——通常是您的扬声器或耳机。

那么这些对象是如何交互的呢?如果您查看我们的 简单 Web 音频示例也可在此处查看实时效果),您将首先看到以下 HTML:

html
<audio src="outfoxing.mp3"></audio>

<button class="paused">Play</button>
<br />
<input type="range" min="0" max="1" step="0.01" value="1" class="volume" />

首先,我们包含一个 <audio> 元素,用于将 MP3 嵌入到页面中。我们不包含任何默认的浏览器控件。接下来,我们包含一个 <button>,我们将用它来播放和停止音乐,以及一个类型为 range 的 <input> 元素,我们将用它来在歌曲播放时调整音轨的音量。

接下来,让我们看看这个例子的 JavaScript。

我们首先创建一个 AudioContext 实例,在其中操作我们的音轨:

js
const audioCtx = new AudioContext();

接下来,我们创建常量来存储对我们的 <audio><button><input> 元素的引用,并使用 AudioContext.createMediaElementSource() 方法创建一个 MediaElementAudioSourceNode,代表我们音频的来源——将从中播放 <audio> 元素:

js
const audioElement = document.querySelector("audio");
const playBtn = document.querySelector("button");
const volumeSlider = document.querySelector(".volume");

const audioSource = audioCtx.createMediaElementSource(audioElement);

接下来,我们添加了几个事件处理程序,用于在按钮按下时在播放和暂停之间切换,并在歌曲播放完毕后将显示重置到开头:

js
// play/pause audio
playBtn.addEventListener("click", () => {
  // check if context is in suspended state (autoplay policy)
  if (audioCtx.state === "suspended") {
    audioCtx.resume();
  }

  // if track is stopped, play it
  if (playBtn.getAttribute("class") === "paused") {
    audioElement.play();
    playBtn.setAttribute("class", "playing");
    playBtn.textContent = "Pause";
    // if track is playing, stop it
  } else if (playBtn.getAttribute("class") === "playing") {
    audioElement.pause();
    playBtn.setAttribute("class", "paused");
    playBtn.textContent = "Play";
  }
});

// if track ends
audioElement.addEventListener("ended", () => {
  playBtn.setAttribute("class", "paused");
  playBtn.textContent = "Play";
});

注意:你们中的一些人可能会注意到,用于播放和暂停音轨的 play()pause() 方法不属于 Web 音频 API;它们是 HTMLMediaElement API 的一部分,后者不同但密切相关。

接下来,我们使用 AudioContext.createGain() 方法创建一个 GainNode 对象,该对象可用于调节通过它的音频音量,并创建另一个事件处理程序,该处理程序在滑块值更改时更改音频图的增益(音量)值:

js
// volume
const gainNode = audioCtx.createGain();

volumeSlider.addEventListener("input", () => {
  gainNode.gain.value = volumeSlider.value;
});

为了使其正常工作,最后要做的是连接音频图中的不同节点,这可以通过在每种节点类型上可用的 AudioNode.connect() 方法来完成:

js
audioSource.connect(gainNode).connect(audioCtx.destination);

音频从源开始,然后连接到增益节点,以便可以调节音频的音量。增益节点再连接到目标节点,以便声音可以在您的计算机上播放(AudioContext.destination 属性表示您的计算机硬件上可用的默认 AudioDestinationNode,例如您的扬声器)。

它们有可识别的入口点

使用 API 时,您应该确保知道 API 的入口点在哪里。在 Web 音频 API 中,这非常简单——它是 AudioContext 对象,需要使用它来执行任何音频操作。

文档对象模型(DOM)API 也有一个简单的入口点——它的功能通常出现在 Document 对象或您想以某种方式影响的 HTML 元素的实例上,例如:

js
const em = document.createElement("em"); // create a new em element
const para = document.querySelector("p"); // reference an existing p element
em.textContent = "Hello there!"; // give em some text content
para.appendChild(em); // embed em inside para

Canvas API 也依赖于获取上下文对象来操作事物,尽管在这种情况下,它是一个图形上下文而不是音频上下文。它的上下文对象是通过获取对您要绘制的 <canvas> 元素的引用,然后调用其 HTMLCanvasElement.getContext() 方法来创建的:

js
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

我们想对画布做的任何事情都通过调用上下文对象(它是 CanvasRenderingContext2D 的一个实例)的属性和方法来实现,例如:

js
Ball.prototype.draw = function () {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
  ctx.fill();
};

注意:您可以在我们的 弹跳球演示中看到此代码的实际运行(也可在此处查看实时运行)。

它们通常使用事件来处理状态变化

我们已经在课程早期的 事件简介文章中讨论过事件,该文章详细介绍了客户端 Web 事件是什么以及它们如何在代码中使用。如果您还不熟悉客户端 Web API 事件的工作原理,您应该先阅读这篇文章,然后再继续。

有些 Web API 不包含事件,但大多数至少包含几个。允许我们在事件触发时运行函数的处理程序属性通常列在我们的参考资料中单独的“事件处理程序”部分。

我们已经在上面的 Web 音频 API 示例中看到了许多事件处理程序的用法:

js
// play/pause audio
playBtn.addEventListener("click", () => {
  // check if context is in suspended state (autoplay policy)
  if (audioCtx.state === "suspended") {
    audioCtx.resume();
  }

  // if track is stopped, play it
  if (playBtn.getAttribute("class") === "paused") {
    audioElement.play();
    playBtn.setAttribute("class", "playing");
    playBtn.textContent = "Pause";
    // if track is playing, stop it
  } else if (playBtn.getAttribute("class") === "playing") {
    audioElement.pause();
    playBtn.setAttribute("class", "paused");
    playBtn.textContent = "Play";
  }
});

// if track ends
audioElement.addEventListener("ended", () => {
  playBtn.setAttribute("class", "paused");
  playBtn.textContent = "Play";
});

它们在适当情况下具有额外的安全机制

WebAPI 功能受到与 JavaScript 和其他 Web 技术(例如同源策略)相同的安全考虑,但它们有时具有额外的安全机制。例如,一些更现代的 WebAPI 仅在通过 HTTPS 提供的页面上有效,因为它们传输可能敏感的数据(示例包括 Service WorkersPush)。

此外,某些 WebAPI 在您的代码中调用它们时,会请求用户允许启用。例如,通知 API 使用弹出对话框请求权限:

A screenshot of the notifications pop-up dialog provided by the Notifications API of the browser. 'mdn.github.io' website is asking for permissions to push notifications to the user-agent with an X to close the dialog and drop-down menu of options with 'always receive notifications' selected by default.

Web 音频和 HTMLMediaElement API 受一项称为自动播放策略的安全机制限制——这基本上意味着您不能在页面加载时自动播放音频——您必须允许用户通过按钮等控件来启动音频播放。这样做是因为自动播放音频通常非常烦人,我们真的不应该让我们的用户遭受这种困扰。

注意:根据浏览器的严格程度,此类安全机制甚至可能会阻止示例在本地运行,即如果您在浏览器中加载本地示例文件而不是从 Web 服务器运行它。在撰写本文时,我们的 Web 音频 API 示例在 Google Chrome 上无法在本地工作——我们必须将其上传到 GitHub 才能使其工作。

总结

至此,您应该对 API 是什么、它们如何工作以及如何在 JavaScript 代码中使用它们有了很好的了解。您可能迫不及待地想开始使用特定的 API 做一些有趣的事情,那么让我们开始吧!接下来,我们将介绍视频和音频 API。