Web API 简介

首先,我们将从高层次的角度来了解 API——它们是什么,它们是如何工作的,如何在代码中使用它们,以及它们的结构?我们还将看一下 API 的不同主要类别,以及它们都有哪些用途。

先决条件 HTMLCSS 和 JavaScript 基础知识的了解(参见 入门构建块JavaScript 对象)。
目标 熟悉 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.

图片来源:超载插座 by The Clear Communication People, on Flickr.

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

注意:另请参见 API 词汇表条目 以获取更多描述。

客户端 JavaScript 中的 API

尤其是客户端 JavaScript,它可以使用许多可用的 API——这些 API 不是 JavaScript 语言本身的一部分,而是构建在核心 JavaScript 语言之上,为你在 JavaScript 代码中使用提供了额外的超能力。它们通常分为两类

  • 浏览器 API 构建在你的 Web 浏览器中,并且能够公开来自浏览器和周围计算机环境的数据,并使用它做一些有用的复杂的事情。例如,Web 音频 API 为 JavaScript 提供了用于在浏览器中操作音频的结构——获取音频轨道,更改其音量,对其应用效果等。在后台,浏览器实际上正在使用一些复杂的低级代码(例如 C++ 或 Rust)来执行实际的音频处理。但是,API 又将这种复杂性从你身边抽象出来。
  • 第三方 API 默认情况下不会内置在浏览器中,通常你必须从 Web 上的某个地方检索它们的代码和信息。例如,Google 地图 API 允许你执行诸如在你的网站上显示到办公室的交互式地图之类的事情。它提供了一组特殊的结构,你可以使用它们来查询 Google 地图服务并返回特定信息。

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 在起作用。在 操作文档 中了解更多关于这些类型的 API 的信息。
  • 从服务器获取数据以自行更新网页的小部分的 API 被广泛使用。这个看似很小的细节对网站的性能和行为产生了巨大的影响——如果你只需要更新股票清单或可用新故事列表,那么无需重新加载整个页面就可以立即执行此操作,这可以使网站或应用程序感觉更具响应性和“快速”。用于此的主要 API 是 Fetch API,虽然较旧的代码可能仍在使用 XMLHttpRequest API。你可能还会遇到术语 Ajax,它描述了这种技术。在 从服务器获取数据 中了解更多关于此类 API 的信息。
  • 用于绘制和操作图形的 API 在浏览器中得到广泛支持——最流行的是 CanvasWebGL,它们允许你以编程方式更新包含在 HTML <canvas> 元素中的像素数据以创建 2D 和 3D 场景。例如,你可以使用 Canvas API 绘制矩形或圆圈之类的形状,将图像导入画布,并对其应用诸如棕褐色或灰度之类的滤镜,或者使用 WebGL 创建具有照明和纹理的复杂 3D 场景。此类 API 通常与用于创建动画循环(例如 window.requestAnimationFrame())和其他 API 结合使用,以制作不断更新的场景,如卡通和游戏。
  • 音频和视频 APIHTMLMediaElementWeb 音频 APIWebRTC 允许你使用多媒体做一些非常有趣的事情,例如为播放音频和视频创建自定义 UI 控件,与你的视频一起显示字幕和字幕之类的文本轨道,从你的网络摄像头获取视频以通过画布(见上文)进行操作或显示在网络会议中其他人的计算机上,或者向音频轨道添加效果(例如增益、失真、平移等)。
  • 设备 API 使你能够与设备硬件交互:例如,使用 地理位置 API 访问设备 GPS 以查找用户的位置。
  • 客户端存储 API 使你能够在客户端存储数据,这样你就可以创建一个应用程序,该应用程序将在页面加载之间保存其状态,甚至在设备脱机时也能工作。有几种可用的选项,例如使用 Web 存储 API 进行简单的名称/值存储,以及使用 IndexedDB API 进行更复杂的数据库存储。

常见的第三方 API

第三方 API 种类繁多;你迟早可能会使用的一些更流行的 API 是

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

API 是如何工作的?

不同的 JavaScript API 以略微不同的方式工作,但通常,它们具有共同的功能和类似的工作主题。

它们基于对象

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

注意:如果你还不熟悉对象的运作方式,你应该在继续之前回顾并完成我们的 JavaScript 对象 模块。

让我们回到 Web Audio 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>,我们将使用它来播放和停止音乐,以及一个类型为范围的 <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 Audio 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 Audio 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 Audio 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 在您代码中对它们进行调用后,会请求用户允许启用它们。例如,Notifications 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 Audio 和 HTMLMediaElement API 受称为 自动播放策略 的安全机制的约束——这基本上意味着您无法在页面加载时自动播放音频——您必须允许您的用户通过按钮之类的控件来启动音频播放。这样做是为了防止自动播放音频,因为自动播放音频通常非常令人讨厌,我们不应该强迫用户忍受它。

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

总结

此时,您应该对什么是 API、它们如何工作以及您可以在 JavaScript 代码中使用它们做什么有一个很好的了解。您可能很兴奋想要开始实际使用特定的 API 来做一些有趣的事情,所以让我们开始吧!接下来,我们将看看如何使用文档对象模型 (DOM) 来操作文档。