摘要:版本号后面是响应状态,首先是一个三位的状态码,然后是一个可读的字符串。以开头的状态码表示请求成功。是最著名的状态码了,表示找不到资源。调用返回一个,它解析为一个对象,该对象包含服务器响应的信息,例如状态码和协议头。
来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:HTTP and Forms
译者:飞龙
协议:CC BY-NC-SA 4.0
自豪地采用谷歌翻译
部分参考了《JavaScript 编程精解(第 2 版)》
通信在实质上必须是无状态的,从客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上存储的任何上下文。
Roy Fielding,《Architectural Styles and the Design of Network-based Software Architectures》
我们曾在第 13 章中提到过超文本传输协议(HTTP),万维网中通过该协议进行数据请求和传输。在本章中会对该协议进行详细介绍,并解释浏览器中 JavaScript 访问 HTTP 的方式。
协议当你在浏览器地址栏中输入eloquentjavascript.net/18_http.html时,浏览器会首先找到和eloquentjavascript.net相关的服务器的地址,然后尝试通过 80 端口建立 TCP 连接,其中 80 端口是 HTTP 的默认通信端口。如果该服务器存在并且接受了该连接,浏览器可能发送如下内容。
GET /18_http.html HTTP/1.1
Host: eloquentjavascript.net
User-Agent: Your browser"s name
然后服务器会通过同一个链接返回如下内容。
HTTP/1.1 200 OK
Content-Length: 65585
Content-Type: text/html
Last-Modified: Mon, 08 Jan 2018 10:29:45 GMT
... the rest of the document
浏览器会选取空行之后的响应部分,也就是正文(不要与 HTML 标签混淆),并将其显示为 HTML 文档。
由客户端发出的信息叫作请求。请求的第一行如下。
GET /17_http.html HTTP/1.1
请求中的第一个单词是请求方法。GET表示我们希望得到一个我们指定的资源。其他常用方式还有DELETE,用于删除一个资源;PUT用于替换资源;POST用于发送消息。需要注意的是服务器并不需要处理所有收到的请求。如果你随机访问一个网站并请求删除主页,服务器很有可能会拒绝你的请求。
方法名后的请求部分是所请求的资源的路径。在最简单的情况下,一个资源只是服务器中的一个文件。不过,协议并没有要求资源一定是实际文件。一个资源可以是任何可以像文件一样传输的东西。很多服务器会实时地生成这些资源。例如,如果你打开github.com/marijnh,服务器会在数据库中寻找名为marijnjh的用户,如果找到了则会为该用户的生成介绍页面。
请求的第一行中位于资源路径后面的HTTP/1.1用来表明所使用的 HTTP 协议的版本。
在实践中,许多网站使用 HTTP v2,它支持与版本 1.1 相同的概念,但是要复杂得多,因此速度更快。 浏览器在与给定服务器通信时,会自动切换到适当的协议版本,并且无论使用哪个版本,请求的结果都是相同的。 由于 1.1 版更直接,更易于使用,因此我们将专注于此。
服务器的响应也是以版本号开始的。版本号后面是响应状态,首先是一个三位的状态码,然后是一个可读的字符串。
HTTP/1.1 200 OK
以 2 开头的状态码表示请求成功。以 4 开头的状态码表示请求中有错误。404 是最著名的 HTTP 状态码了,表示找不到资源。以 5 开头的状态码表示服务器端出现了问题,而请求没有问题。
请求或响应的第一行后可能会有任意个协议头,多个形如name: value的行表明了和请求或响应相关的更多信息。这些是示例响应中的头信息。
Content-Length: 65585
Content-Type: text/html
Last-Modified: Thu, 04 Jan 2018 14:05:30 GMT
这些信息说明了响应文档的大小和类型。在这个例子中,响应是一个 65585 字节的 HTML 文档,同时也说明了该文档最后的更改时间。
多数大多数协议头,客户端或服务器可以自由决定需要在请求或响应中包含的协议头,不过也有一些协议头是必需的。例如,指明主机名的Host头在请求中是必须的,因为一个服务器可能在一个 IP 地址下有多个主机名服务,如果没有Host头,服务器则无法判断客户端尝试请求哪个主机。
请求和响应可能都会在协议头后包含一个空行,后面则是消息体,包含所发送的数据。GET和DELETE请求不多带带发送任何数据,但PUT和POST请求则会。同样地,一些响应类型(如错误响应)不需要有消息体。
浏览器和 HTTP正如上例所示,当我们在浏览器地址栏输入一个 URL 后浏览器会发送一个请求。当 HTML 页面中包含有其他的文件,例如图片和 JavaScript 文件时,浏览器也会一并获取这些资源。
一个较为复杂的网站通常都会有 10 到 200 个不等的资源。为了可以很快地取得这些资源,浏览器会同时发送多个GET请求,而不是一次等待一个请求。此类文档都是通过GET方法来获取的。
HTML页面可能包含表单,用户可以在表单中填入一些信息然后由浏览器将其发送到服务器。如下是一个表单的例子。
这段代码描述了一个有两个输入字段的表单:较小的输入字段要求用户输入姓名,较大的要求用户输入一条消息。当点击发送按钮时,表单就提交了,这意味着其字段的内容被打包到 HTTP 请求中,并且浏览器跳转到该请求的结果。
当
在 JavaScript 中submit事件有多种用途。我们可以编写代码来检测用户输入是否正确并且立刻提示错误信息,而不是提交表单。或者我们可以禁用正常的提交方式,正如这个例子中,让我们的程序处理输入,可能使用fetch将其发送到服务器而不重新加载页面。
文本字段由type属性为text或password的标签和textarea标签组成的字段有相同的接口。其 DOM 元素都有一个value属性,保存了为字符串格式的当前内容。将这个属性更改为另一个值将改变字段的内容。
文本字段selectionStart和selectEnd属性包含光标和所选文字的信息。当没有选中文字时,这两个属性的值相同,表明当前光标的信息。例如,0 表示文本的开始,10 表示光标在第十个字符之后。当一部分字段被选中时,这两个属性值会不同,表明选中文字开始位置和结束位置。
和正常的值一样,这些属性也可以被更改。
想象你正在编写关于 Knaseknemwy 的文章,但是名字拼写有一些问题,后续代码将
replaceSelection函数用给定的字符串替换当前选中的文本字段内容,并将光标移动到替换内容后让用户可以继续输入。change事件不会在每次有输入时都被调用,而是在内容在改变并失焦后触发。为了及时的响应文本字段的改变,则需要为input事件注册一个处理器,每当用户有输入或更改时就被触发。
下面的例子展示一个文本字段和一个展示字段中的文字的当前长度的计数器。
length: 0
选择框和单选框
一个选择框只是一个双选切换。其值可以通过其包含一个布尔值的checked属性来获取和更改。
标签关联部分文本和一个输入字段。点击标签上的任何位置将激活该字段,这样会将其聚焦,并当它为复选框或单选按钮时切换它的值。
单选框和选择框类似,不过单选框可以通过相同的name属性,隐式关联其他几个单选框,保证只能选择其中一个。
Color:
提供给querySelectorAll的 CSS 查询中的方括号用于匹配属性。 它选择name属性为"color"的元素。
选择字段选择字段和单选按钮比较相似,允许用户从多个选项中选择。但是,单选框的展示排版是由我们控制的,而标签将允许用户选择任意数量的选项,而不仅仅是一个选项。 在大多数浏览器中,这会显示与正常的选择字段不同的效果,后者通常显示为下拉控件,仅在你打开它时才显示选项。
每一个选项会有一个值,这个值可以通过value属性来定义。如果没有提供,选项内的文本将作为其值。字段的标签可以通过一个类似于数组对象的options属性访问到。每个选项会有一个叫作selected的属性,来表明这个选项当前是否被选中。这个属性可以用来被设定选中或不选中。
这个例子会从多选字段中取出选中的数值,并使用这些数值构造一个二进制数字。按住CTRL(或 Mac 的COMMAND键)来选择多个选项。
= 0
文件字段
文件字段最初是用于通过表单来上传从浏览器机器中获取的文件。在现代浏览器中,也可以从 JavaScript 程序中读取文件。该字段则作为一个看门人角色。脚本不能简单地直接从用户的电脑中读取文件,但是如果用户在这个字段中选择了一个文件,浏览器会将这个行为解释为脚本,便可以访问该文件。
一个文本字段是一个类似于“选择文件”或“浏览”标签的按钮,后面跟着所选文件的信息。
文本字段的files属性是一个类数组对象(当然,不是一个真正的数组),包含在字段中所选择的文件。开始时是空的。因此文本字段属性不仅仅是file属性。有时文本字段可以上传多个文件,这使得同时选择多个文件变为可能。
files对象中的对象有name(文件名)、size(文件大小,单位为字节),和type(文件的媒体类型,如text/plain,image/jpeg)等属性。
而files属性中不包含文件内容的属性。获取这个内容会比较复杂。由于从硬盘中读取文件会需要一些时间,接口必须是异步的,来避免文档的无响应问题。
读取文件是通过FileReader对象实现的,注册一个load事件处理器,然后调用readAsText方法,传入我们希望读取的文件,一旦载入完成,reader的result属性内容就是文件内容。
FileReader对象还会在读取文件失败时触发error事件。错误对象本身会存在reader的error属性中。这个接口是在Promise成为语言的一部分之前设计的。 你可以把它包装在Promise中,像这样:
function readFileText(file) { return new Promise((resolve, reject) => { let reader = new FileReader(); reader.addEventListener( "load", () => resolve(reader.result)); reader.addEventListener( "error", () => reject(reader.error)); }); reader.readAsText(file); }); }客户端保存数据
采用 JavaScript 代码的简单 HTML 页面可以作为实现一些小应用的很好的途径。可以采用小的帮助程序来自动化一些基本的任务。通过关联一些表单字段和事件处理器,你可以实现华氏度与摄氏度的转换。也可以实现由主密码和网站名来生成密码等各种任务。
当一个应用需要存储一些东西以便于跨对话使用时,则不能使用 JavaScript 绑定因为每当页面关闭时这些值就会丢失。你可以搭建一个服务器,连接到因特网,将一些服务数据存储到其中。在第20章中将会介绍如何实现这些,当然这需要很多的工作,也有一定的复杂度。有时只要将数据存储在浏览器中即可。
localStorage对象可以用于保存数据,它在页面重新加载后还存在。这个对象允许你将字符串存储在某个名字(也是字符串)下,下面是具体示例。
localStorage.setItem("username", "marijn"); console.log(localStorage.getItem("username")); // → marijn localStorage.removeItem("username");
一个在localStorage中的值会保留到其被重写时,它也可以通过removeItem来清除,或者由用户清除本地数据。
不同字段名的站点的数据会存在不同的地方。这也表明原则上由localStorage存储的数据只可以由相同站点的脚本编辑。
浏览器的确限制一个站点可以存储的localStorage的数据大小。这种限制,以及用垃圾填满人们的硬盘并不是真正有利可图的事实,防止该特性占用太多空间。
下面的代码实现了一个粗糙的笔记应用。程序将用户的笔记保存为一个对象,将笔记的标题和内容字符串相关联。对象被编码为 JSON 格式并存储在localStorage中。用户可以从
脚本从存储在localStorage中的"Notes"值来获取它的初始状态,如果其中没有值,它会创建示例状态,仅仅带有一个购物列表。从localStorage中读取不存在的字段会返回null。
setState方法确保 DOM 显示给定的状态,并将新状态存储到localStorage。 事件处理器调用这个函数来移动到一个新状态。
在这个例子中使用Object.assign,是为了创建一个新的对象,它是旧的state.notes的一个克隆,但是添加或覆盖了一个属性。 Object.assign选取第一个参数,向其添加所有更多参数的所有属性。 因此,向它提供一个空对象会使它填充一个新对象。 第三个参数中的方括号表示法,用于创建名称基于某个动态值的属性。
还有另一个和localStorage很相似的对象叫作sessionStorage。这两个对象之间的区别在于sessionStorage的内容会在每次会话结束时丢失,而对于多数浏览器来说,会话会在浏览器关闭时结束。
本章小结在本章中,我们讨论了 HTTP 协议的工作原理。 客户端发送一个请求,该请求包含一个方法(通常是GET)和一个标识资源的路径。 然后服务器决定如何处理请求,并用状态码和响应正文进行响应。 请求和响应都可能包含提供附加信息的协议头。
浏览器 JavaScript 可以通过fetch接口生成 HTTP 请求。 像这样生成请求:
fetch("/18_http.html").then(r => r.text()).then(text => { console.log(`The page starts with ${text.slice(0, 15)}`); });
浏览器生成GET请求来获取显示网页所需的资源。 页面也可能包含表单,这些表单允许在提交表单时,用户输入的信息发送为新页面的请求。
HTML可以表示多种表单字段,例如文本字段、选择框、多选字段和文件选取。
这些字段可以用 JavaScript 进行控制和读取。内容改变时会触发change事件,文本有输入时会触发input事件,键盘获得焦点时触发键盘事件。 例如"value"(用于文本和选择字段)或"checked"(用于复选框和单选按钮)的属性,用于读取或设置字段的内容。
当一个表单被提交时,会触发其submit事件,JavaScript 处理器可以通过调用preventDefault来禁用默认的提交事件。表单字段的元素不一定需要被包装在
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105045.html
摘要:来源编程精解中文第三版翻译项目原文译者飞龙协议自豪地采用谷歌翻译部分参考了编程精解第版,这是一本关于指导电脑的书。在可控的范围内编写程序是编程过程中首要解决的问题。我们可以用中文来描述这些指令将数字存储在内存地址中的位置。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Introduction 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地...
摘要:在本例中,使用属性指定链接的目标,其中表示超文本链接。您应该认为和元数据隐式出现在示例中,即使它们没有实际显示在文本中。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:JavaScript and the Browser 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)》 ...
摘要:在这样的程序中,异步编程通常是有帮助的。最初是为了使异步编程简单方便而设计的。在年设计时,人们已经在浏览器中进行基于回调的编程,所以该语言的社区用于异步编程风格。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Node.js 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)...
摘要:事件与节点每个浏览器事件处理器被注册在上下文中。事件对象虽然目前为止我们忽略了它,事件处理器函数作为对象传递事件对象。若事件处理器不希望执行默认行为通常是因为已经处理了该事件,会调用事件对象的方法。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Handling Events 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分...
摘要:相反,当响应指针事件时,它会调用创建它的代码提供的回调函数,该函数将处理应用的特定部分。回调函数可能会返回另一个回调函数,以便在按下按钮并且将指针移动到另一个像素时得到通知。它们为组件构造器的数组而提供。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Project: A Pixel Art Editor 译者:飞龙 协议:CC BY-NC-SA 4...
阅读 2262·2023-04-25 19:06
阅读 1476·2021-11-17 09:33
阅读 1869·2019-08-30 15:53
阅读 2672·2019-08-30 14:20
阅读 3622·2019-08-29 12:58
阅读 3633·2019-08-26 13:27
阅读 595·2019-08-26 12:23
阅读 571·2019-08-26 12:22