推荐阅读:JavaScript书中的第11章和第18章
HTTP是浏览器用来与web服务器通信的协议。当蒂姆·伯纳斯-李开发HTTP时,他设想了一些比仅仅获取网页的系统更复杂的东西。在他对网络的最初设想中,他设想了一个系统,在这个系统中,用户可以获取网页,在浏览器中编辑它们,并将他们的编辑上传到网络服务器。为了方便起见,他为HTTP提供了四个不同的动词。
动词 | 它是做什么的 |
---|---|
得到 | 获取数据(通常是一个网页) |
帖子 | 上传数据到服务器 |
把 | 更新服务器上的数据 |
删除 | 从服务器中删除数据 |
除了适应一系列数据操作之外,HTTP还提供了传输数据的标准化方法。例如,当浏览器向服务器发送GET命令时,它知道期望响应中的数据。具体来说,当响应返回时,它将具有一个主体,所请求的数据将出现在该主体中。同样,发送到服务器的POST命令可以有一个主体,该主体可以包含我们想要上传到服务器的数据。
赢博体育这一切的结果是,HTTP从一开始就被构建为一个管理浏览器和服务器之间来回数据流的系统。这些功能中的大多数多年来一直处于休眠状态,没有被使用。尽管如此,最终还是有人想出了如何充分利用HTTP的强大功能来创建基于web和HTTP的数据架构。该体系结构称为REST,它使用HTTP(动词和url)以及数据表示(XML或JSON)来构建完整的计算基础结构。REST是现代web编程风格的另一个关键元素,因为现代web赢博体育程序被设计为与基于REST的服务器交互,这些服务器提供了所谓的RESTful web服务。
为了开始解释REST web服务是如何工作的,我在我们的类web服务器机器上设置了一个简单的web服务。这个web服务提供菜单项的数据和虚拟咖啡馆的订单。在今天的主要示例中,我们将使用web服务将菜单项列表下载到web页面,并允许我们下订单并将其上传到服务器。
为了发送一个下载菜单项的请求,我们向URL发送一个GET请求:
https://cmsc106.net/cafe/item
作为回报,web服务将通过提供一些数据来响应。在这种情况下,web服务将响应
[{“iditem”:1、“名称”:“早餐卷饼”,“成本”:495年,“饭”:“早餐”},…{“iditem”:10“名称”:“炒”、“成本”:895年,“饭”:“晚餐”}]
这是一个JSON编码的咖啡馆菜单项列表。
由于我们将使用web服务作为数据源,因此接下来需要讨论如何从JavaScript程序中联系web服务。现代JavaScript提供了fetch API,使REST请求变得容易。
下面的示例代码演示了fetch() get请求是如何工作的:
fetch('https://cmsc106.net/cafe/item') .then(response => response.json()) .then(response => receiveItems(response));
fetch()方法以URL作为参数并发起请求。获取()返回一个叫做promise的特殊对象。然后,我们调用promise对象上的then()方法,将一些代码交给它,以便在promise有结果时运行。我们在这里调用then()两次:第一次调用从服务器获取响应的文本(我们事先知道将是JSON代码),并将其转换为对象数组。第二个调用将从服务器接收到的对象列表传递给处理数据的函数。
一旦用户选择了一些项目订购,并在订单表单中输入了他们的姓名和电话号码,我们将希望将他们的订单发送到服务器。下面的代码展示了如何使用fetch() API执行POST:
let toPost = {customer:nameField.value,phone:phoneField.value,items:ids};// POST到服务器取回('https://cmsc106.net/cafe/purchase‘,{方法:’POST‘,主体:json .stringify(toPost),报头:{’Content-type': 'application/json;charset=UTF-8'}})。然后(response => response.json())。then(response => showConfirm(response));
今天的示例程序还演示了一些新的DOM操作技术。第一种特殊技术涉及到页面的结构。如果你看一下页面的HTML,你会发现页面的主体有以下总体结构:
<body> <div id="starting"> <p>Loading data…</p> </div> <div id="view">…HTML显示菜单</div> <div id="order">…HTML显示订单详细信息</div> <div id="confirm">…HTML显示确认消息</div> </body>
对于用户来说,赢博体育程序看起来像几个不同的页面:一个显示菜单的页面,一个显示订单的页面,以及一个在下订单时显示确认消息的页面。实际上,此赢博体育程序的HTML代码由一个页面组成,其中包含四个不同的div。随着赢博体育程序的运行,我们将显示和隐藏这些div,以创建用户正在通过一系列不同页面移动的错觉。
为了显示和隐藏div,我们使用如下代码。在赢博体育程序的setUp()函数中我们这样做
let menuDiv = document.getElementById('view');menuDiv.style.display = 'none';let orderDiv = document.getElementById('order');orderDiv.style.display = 'none';let confirmDiv = document.getElementById('confirm');confirmDiv.style.display = 'none';
这将隐藏除第一个以外的赢博体育div。一旦我们成功地从服务器接收到菜单数据,我们就开始操作
let startingDiv = document.getElementById('start ');startingDiv.style.display = 'none';let menuDiv = document.getElementById('view');menuDiv.style.display = 'block';
这将隐藏显示加载消息的div和显示菜单的div。
下一个特殊功能涉及我们在赢博体育程序中的表中放置的一些按钮。例如,在显示菜单项的表中,我们希望向每行添加一个订购按钮,以便用户可以订购菜单中的项目。
下面是构建菜单表的代码:
function displayItems(items){//从表中删除任何现有的条目let tableBody = document.getElementById('menu');tableBody。innerHTML = ";//为列表中的项目添加新行let length = items.length;for(let n = 0;n < length;n++) {let newRow = document.createElement('tr');启动。innerHTML = ' < td类=“align-middle”>“[n] . name + +项目”< / td > < td类=“align-middle”>“美元+项目[n] .cost / 100 +的< / td >;let orderButton = document.createElement('button');orderButton。innerText = 'Order';orderButton.addEventListener(“点击”,()= > orderItem(项目[n] .iditem));orderButton。setAttribute('class','btn -secondary align-middle');let buttonTD = document.createElement('td');buttonTD.appendChild (orderButton);newRow.appendChild (buttonTD);tableBody.appendChild(启动);}}
这里的许多逻辑重复了我展示的第一个Cafe示例。我们在这里使用DOM技术构建要添加到表中的tr个元素。一个新特性是,我们希望每个表行还包含一个按钮,用户可以单击该按钮来订购该商品。正如您在这里看到的,JavaScript代码创建了一个按钮元素,设置了它的文本和类,然后还为它附加了一个事件处理程序。然后我们还构造一个td元素,将按钮放在td中,最后将td追加为该行的子元素。