Web API 简介

首先,我们将从高层次上了解 API - 它们是什么、它们如何工作、如何在代码中使用它们以及它们的结构如何?我们还将了解 API 的不同主要类别以及它们的用途。

¥First up, we'll start by looking at APIs from a high level — what are they, how do they work, how to use them in your code, and how are they structured? We'll also take a look at what the different main classes of APIs are, and what kind of uses they have.

先决条件: HTMLCSS 和 JavaScript 基础知识有基本了解(请参阅 第一步架构模块JavaScript 对象)。
目标: 熟悉 API、它们的功能以及如何在代码中使用它们。

什么是 API?

¥What are APIs?

应用编程接口 (API) 是编程语言中提供的结构,允许开发者更轻松地创建复杂的功能。它们将更复杂的代码从你那里抽象出来,提供一些更简单的语法来代替它。

¥Application Programming Interfaces (APIs) are constructs made available in programming languages to allow developers to create complex functionality more easily. They abstract more complex code away from you, providing some easier syntax to use in its place.

作为一个现实世界的例子,考虑一下你的房屋、公寓或其他住宅的电力供应。如果你想在家里使用电器,只需将其插入插座即可工作。你不会尝试将其直接连接到电源 - 这样做的效率非常低,而且如果你不是电工,尝试起来会很困难且危险。

¥As a real-world example, think about the electricity supply in your house, apartment, or other dwellings. If you want to use an appliance in your house, you plug it into a plug socket and it works. You don't try to wire it directly into the power supply — to do so would be really inefficient and, if you are not an electrician, difficult and dangerous to attempt.

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 清晰沟通的人,在 Flickr 上。

¥Image source: Overloaded plug socket by The Clear Communication People, on Flickr.

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

¥In the same way, if you want to say, program some 3D graphics, it is a lot easier to do it using an API written in a higher-level language such as JavaScript or Python, rather than try to directly write low-level code (say C or C++) that directly controls the computer's GPU or other graphics functions.

注意:另请参阅 API 术语表条目 了解更多说明。

¥Note: See also the API glossary entry for further description.

客户端 JavaScript 中的 API

¥APIs in client-side JavaScript

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

¥Client-side JavaScript, in particular, has many APIs available to it — these are not part of the JavaScript language itself, rather they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code. They generally fall into two categories:

  • 浏览器 API 内置于你的 Web 浏览器中,能够公开来自浏览器和周围计算机环境的数据,并用它执行有用的复杂操作。例如,Web 音频 API 提供了用于在浏览器中操作音频的 JavaScript 结构 - 获取音轨、改变其音量、对其应用效果等。在后台,浏览器实际上使用一些复杂的较底层代码(例如 C++ 或 Rust)来进行实际的音频处理。但同样,这种复杂性已被 API 抽象化。
  • 默认情况下,第三方 API 并未内置到浏览器中,你通常必须从 Web 上的某个位置检索它们的代码和信息。例如,谷歌地图 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 工具之间的关系

¥Relationship between JavaScript, APIs, and other JavaScript tools

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

¥So above, we talked about what client-side JavaScript APIs are, and how they relate to the JavaScript language. Let's recap this to make it clearer, and also mention where other JavaScript tools fit in:

  • JavaScript — 一种内置于浏览器中的高级脚本语言,允许你在网页/应用上实现功能。请注意,JavaScript 在其他编程环境中也可用,例如 节点
  • 浏览器 API — 内置于浏览器中的结构,位于 JavaScript 语言之上,可让你更轻松地实现功能。
  • 第三方 API — 内置于第三方平台(例如 Disqus、Facebook)中的构造,允许你在自己的网页中使用这些平台的某些功能(例如,在网页上显示你的 Disqus 评论)。
  • JavaScript 库 — 通常是一个或多个包含 自定义功能 的 JavaScript 文件,你可以将其附加到网页上以加速或启用常见功能的编写。示例包括 jQuery、Mootools 和 React。
  • JavaScript 框架 - JavaScript 框架(例如 Angular 和 Ember)的下一步往往是 HTML、CSS、JavaScript 和其他技术的包,你可以安装这些包,然后使用它们从头开始编写整个 Web 应用。库和框架之间的主要区别是 "控制反转"。当从库中调用方法时,开发者处于控制之中。使用框架,控制是相反的:框架调用开发者的代码。

API 可以做什么?

¥What can APIs do?

现代浏览器中有大量可用的 API,可让你在代码中执行各种操作。通过查看 MDN API 索引页面,你可以看到这一点。

¥There are a huge number of APIs available in modern browsers that allow you to do a wide variety of things in your code. You can see this by taking a look at the MDN APIs index page.

常见浏览器 API

¥Common browser APIs

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

¥In particular, the most common categories of browser APIs you'll use (and which we'll cover in this module in greater detail) are:

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

常用第三方 API

¥Common third-party APIs

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

¥Third-party APIs come in a large variety; some of the more popular ones that you are likely to make use of sooner or later are:

  • 地图 API,例如 地图探索谷歌地图 API,允许你使用网页上的地图执行各种操作。
  • Facebook API 套件,使你能够使用 Facebook 生态系统的各个部分来使你的应用受益,例如通过使用 Facebook 登录提供应用登录、接受应用内支付、推出有针对性的广告活动等。
  • 电报 API,除了提供对机器人的支持之外,还允许你在你的网站上嵌入来自 Telegram 通道的内容。
  • YouTube API,允许你在网站上嵌入 YouTube 视频、搜索 YouTube、构建播放列表等。
  • Pinterest API,它提供了管理 Pinterest 版块和图钉的工具,以便将它们包含在你的网站中。
  • Twilio API,它提供了一个框架,用于在你的应用中构建语音和视频通话功能、从你的应用发送短信/彩信等。
  • Disqus API,它提供了一个可以集成到你的网站中的评论平台。
  • 乳齿象 API,使你能够以编程方式操纵 Mastodon 社交网络的功能。
  • IFTTT API,可通过一个平台集成多个 API。

API 如何工作?

¥How do APIs work?

不同的 JavaScript API 的工作方式略有不同,但一般来说,它们具有共同的功能和相似的工作主题。

¥Different JavaScript APIs work in slightly different ways, but generally, they have common features and similar themes to how they work.

它们是基于对象的

¥They are based on objects

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

¥Your code interacts with APIs using one or more JavaScript objects, which serve as containers for the data the API uses (contained in object properties), and the functionality the API makes available (contained in object methods).

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

¥Note: If you are not already familiar with how objects work, you should go back and work through our JavaScript objects module before continuing.

让我们回到 Web Audio API 的示例 - 这是一个相当复杂的 API,由许多对象组成。最明显的是:

¥Let's return to the example of the Web Audio API — this is a fairly complex API, which consists of a number of objects. The most obvious ones are:

  • AudioContext,它代表可用于操纵浏览器内播放的音频的 音频图,并且具有许多可用于操纵该音频的方法和属性。
  • MediaElementAudioSourceNode,它代表 <audio> 元素,其中包含你想要在音频上下文中播放和操作的声音。
  • AudioDestinationNode,代表音频的目的地,即计算机上实际输出音频的设备 - 通常是扬声器或耳机。

那么这些对象如何相互作用呢?如果你查看我们的 简单的网络音频示例 (也看到它直播),你将首先看到以下 HTML:

¥So how do these objects interact? If you look at our simple web audio example (see it live also), you'll first see the following 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> 元素,我们将使用它来调整正在播放的曲目的音量。

¥We, first of all, include an <audio> element with which we embed an MP3 into the page. We don't include any default browser controls. Next, we include a <button> that we'll use to play and stop the music, and an <input> element of type range, which we'll use to adjust the volume of the track while it's playing.

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

¥Next, let's look at the JavaScript for this example.

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

¥We start by creating an AudioContext instance inside which to manipulate our track:

js
const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();

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

¥Next, we create constants that store references to our <audio>, <button>, and <input> elements, and use the AudioContext.createMediaElementSource() method to create a MediaElementAudioSourceNode representing the source of our audio — the <audio> element will be played from:

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

const audioSource = audioCtx.createMediaElementSource(audioElement);

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

¥Next up we include a couple of event handlers that serve to toggle between play and pause when the button is pressed and reset the display back to the beginning when the song has finished playing:

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 的一部分,虽然不同但密切相关。

¥Note: Some of you may notice that the play() and pause() methods being used to play and pause the track are not part of the Web Audio API; they are part of the HTMLMediaElement API, which is different but closely-related.

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

¥Next, we create a GainNode object using the AudioContext.createGain() method, which can be used to adjust the volume of audio fed through it, and create another event handler that changes the value of the audio graph's gain (volume) whenever the slider value is changed:

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

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

要使其正常工作,最后要做的事情是将音频图中的不同节点连接起来,这是使用每个节点类型上可用的 AudioNode.connect() 方法完成的:

¥The final thing to do to get this to work is to connect the different nodes in the audio graph up, which is done using the AudioNode.connect() method available on every node type:

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

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

¥The audio starts in the source, which is then connected to the gain node so the audio's volume can be adjusted. The gain node is then connected to the destination node so the sound can be played on your computer (the AudioContext.destination property represents whatever is the default AudioDestinationNode available on your computer's hardware, e.g. your speakers).

他们有可识别的入口点

¥They have recognizable entry points

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

¥When using an API, you should make sure you know where the entry point is for the API. In The Web Audio API, this is pretty simple — it is the AudioContext object, which needs to be used to do any audio manipulation whatsoever.

文档对象模型 (DOM) API 也有一个简单的入口点 - 它的功能往往挂在 Document 对象上,或者是你想要以某种方式影响的 HTML 元素的实例,例如:

¥The Document Object Model (DOM) API also has a simple entry point — its features tend to be found hanging off the Document object, or an instance of an HTML element that you want to affect in some way, for example:

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

画布 API 还依赖于获取上下文对象来操作事物,尽管在本例中,它是图形上下文而不是音频上下文。它的上下文对象是通过获取对要绘制的 <canvas> 元素的引用来创建的,然后调用它的 HTMLCanvasElement.getContext() 方法:

¥The Canvas API also relies on getting a context object to use to manipulate things, although in this case, it's a graphical context rather than an audio context. Its context object is created by getting a reference to the <canvas> element you want to draw on, and then calling its HTMLCanvasElement.getContext() method:

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

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

¥Anything that we want to do to the canvas is then achieved by calling properties and methods of the context object (which is an instance of CanvasRenderingContext2D), for example:

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();
};

注意:你可以在我们的 弹跳球演示 中看到此代码的运行情况(也可以参见 实时运行)。

¥Note: You can see this code in action in our bouncing balls demo (see it running live also).

他们经常使用事件来处理状态的变化

¥They often use events to handle changes in state

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

¥We already discussed events earlier on in the course in our Introduction to events article, which looks in detail at what client-side web events are and how they are used in your code. If you are not already familiar with how client-side web API events work, you should go and read this article first before continuing.

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

¥Some web APIs contain no events, but most contain at least a few. The handler properties that allow us to run functions when events fire are generally listed in our reference material in separate "Event handlers" sections.

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

¥We already saw a number of event handlers in use in our Web Audio API example above:

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";
});

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

¥They have additional security mechanisms where appropriate

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

¥WebAPI features are subject to the same security considerations as JavaScript and other web technologies (for example same-origin policy), but they sometimes have additional security mechanisms in place. For example, some of the more modern WebAPIs will only work on pages served over HTTPS due to them transmitting potentially sensitive data (examples include Service Workers and Push).

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

¥In addition, some WebAPIs request permission to be enabled from the user once calls to them are made in your code. As an example, the Notifications API asks for permission using a pop-up dialog box:

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 受名为 自动播放政策 的安全机制的约束 — 这基本上意味着你无法在页面加载时自动播放音频 — 你必须允许用户通过按钮等控件启动音频播放。这样做是因为自动播放音频通常非常烦人,我们真的不应该让我们的用户受到它的影响。

¥The Web Audio and HTMLMediaElement APIs are subject to a security mechanism called autoplay policy — this basically means that you can't automatically play audio when a page loads — you've got to allow your users to initiate audio play through a control like a button. This is done because autoplaying audio is usually really annoying and we really shouldn't be subjecting our users to it.

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

¥Note: Depending on how strict the browser is, such security mechanisms might even stop the example from working locally, i.e. if you load the local example file in your browser instead of running it from a web server. At the time of writing, our Web Audio API example wouldn't work locally on Google Chrome — we had to upload it to GitHub before it would work.

概括

¥Summary

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

¥At this point, you should have a good idea of what APIs are, how they work, and what you can do with them in your JavaScript code. You are probably excited to start actually doing some fun things with specific APIs, so let's go! Next up, we'll look at manipulating documents with the Document Object Model (DOM).