2018-6-26更新
304状态码 : Not Modified ---- 页面未被修改,缓存是最新的
304自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。 如果网页自请求者上次请求后再也没有更改过,您应将服务器配置为返回此响应(称为 If-Modified-Since HTTP 标头)。
当一个客户端(通常是浏览器)向web服务器发送一个请求,如果web服务器返回304响应,则表示此请求的本地缓存是最新的,可以直接使用。这种方法可以节省带宽,避免重复响应。
304状态码总结:
- modified:是修改的意思 -------- ( not modified未被修改 )
- 304状态码表示自上次请求后,请求的网页未被修改过,缓存是最新的,可以直接使用。
- 当状态码是304的时候,服务器返回的body为空
- 304状态码和Last-Modified ,If-Modified-Since有关 ----------- ( 重要 )
- Last-Modified : 是由服务器往客户端发送的 HTTP 头
- If-Modified-Since : 是由客户端往服务器发送的 HTTP 头
- 304状态码和If-None-Match,ETags有关 ------------------------- ( 重要 )
- If-None-Match,和ETags常用来判断当前请求资源是否改变。
- 区别:
(Last-Modified,If-Modified-Since )
和(If-None-Match, ETags)
Last-Modified和IF-Modified-Since只判断资源的最后修改时间,
而ETags和If-None-Match可以是资源任何的任何属性,比如资源的MD5等。 - ETags和If-None-Match的工作原理是在HTTP Response中添加ETags信息。当客户端再次请求该资源时,将在HTTP Request中加入If-None-Match信息(ETags的值)。如果服务器验证资源的ETags没有改变(该资源没有改变),将返回一个304状态,否则,服务器将返回200状态,并返回该资源和新的ETags。
-
Etag的优先级高于Last-Modified
--------------------------------------- ( 重要 ) -
(Etag 和 If-None-Match)
优于(Last-Modified 和 If-Modified-Since)
的地方:
(1)、Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间;
(2)、如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存;
(3)、有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形。
然而,Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。
ETag 和 If-None-Match
- ETag和If-None-Match的工作原理是在HTTP Response中添加ETags信息。当客户端再次请求该资源时,将在HTTP Request中加入If-None-Match信息(ETags的值)。如果服务器验证资源的ETags没有改变(该资源没有改变),将返回一个304状态;否则,服务器将返回200状态,并返回该资源和新的ETags。
什么是”Etag”? --------------------------- ( 重要 )
典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:
ETag: "50b1c1d4f775c61:df3"
客户端的查询更新格式是这样的:
If-None-Match: W/"50b1c1d4f775c61:df3"
如果ETag没改变,则返回状态304然后不返回body,这也和Last-Modified一样。
Etag主要在断点下载时比较有用。
说白了,
ETag 实体标签: 一般为资源实体的哈希值
即ETag就是服务器生成的一个标记,用来标识返回值是否有变化。
且Etag的优先级高于Last-Modified。
ETag的原理
它的原理是这样的,当浏览器请求服务器的某项资源(A)时, 服务器根据A算出一个哈希值(3f80f-1b6-3e1cb03b)并通过 ETag 返回给浏览器,浏览器把"3f80f-1b6-3e1cb03b" 和 A 同时缓存在本地,当下次再次向服务器请求A时,会通过类似 If-None-Match: "3f80f-1b6-3e1cb03b" 的请求头把ETag发送给服务器,服务器再次计算A的哈希值并和浏览器返回的值做比较,如果发现A发生了变化就把A返回给浏览器(200),如果发现A没有变化就给浏览器返回一个304未修改。这样通过控制浏览器端的缓存,可以节省服务器的带宽,因为服务器不需要每次都把全量数据返回给客户端。
Last-Modified 和 If-Modified-Since
再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了
- 这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。
什么是”Last-Modified”? --------------- ( 重要 )
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
ETage 和 If-None-Match https://www.cnblogs.com/softidea/p/5986339.html
Last-Modified https://blog.csdn.net/taipingliebeiluo/article/details/5842766
https://www.cnblogs.com/huenchao/p/6104709.html
(一) 请求头-请求报文头属性
(1) Accept
请求报文通过 Accept 报文头属性告诉服务端 - 客户端接受什么类型的响应。
( Accept : 接受 )
- 浏览器发送的accept字段只是建议值,服务器是否使用这个值由服务端程序决定。
如果服务端按Restful规范开发接口的话,可以考虑根据accept的不同值返回不同格式的内容。同一份数据可以按json, xml格式分别输出。 - 如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)
- 通配符 * 代表任意类型
Accept: */* 代表浏览器可以处理所有类型,(一般浏览器发给服务器都是发这个)
Accept:text/html:HTML格式的文本文档
Accept:text/plain:普通的ASCⅡ文本文档
Accept:image/jpeg:JPEG格式的图片
Accept:image/gif:GIF格式的图片
(2) Content-Type
Content-Type属性指定请求和响应的HTTP内容类型。 (内容)
如果未指定 ContentType,默认为text/html。
- Content-Type 是Http的实体首部字段,用于说明请求或返回的消息主体是用何种方式编码,在request header和response header里都存在。
- enctype 是编码方式的意思
Content-Type:请求的与实体对应的MIME信息 -------------------------------------------- (重要)
1.text/html
2.text/plain
3.text/css
4.text/javascript
5.application/x-www-form-urlencoded
6.multipart/form-data
7.application/json
8.application/xml
前面几个都很好理解,都是html,css,javascript的文件类型,后面四个是POST的发包方式。
(1) Content-Type: application/json;
Content-Type: application/json 用来告诉服务端消息主体是序列化后的 JSON 字符串。
传递的是一个json对象,并不是直接丢一个对象过去,需要进行序列化,JSON.stringify(data)
(2) Content-Type: application/x-www-form-urlencoded
application/x-www-form-urlencoded是常用的表单发包方式,普通的表单提交,或者js发包,默认都是通过这种方式
表单:
<form enctype="application/x-www-form-urlencoded" ----------------------------!!!
action="http://homeway.me/post.php" method="POST">
<input type="text" name="name" value="homeway">
<input type="text" name="key" value="nokey">
<input type="submit" value="submit">
</form>
务器收到的raw header:
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,gl;q=0.2,de;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:17
Content-Type:application/x-www-form-urlencoded ------------------------------!!!
服务器收到的raw body
name=homeway&key=nokey ------------------------------!!!
(3) Content-Type:multipart/form-data;
我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。
(4) Content-Type: text/xml
微信用的是这种数据格式发送请求的。
accept-Charset:浏览器通过这个头告诉服务器,它支持哪种字符集。
accept-encoding:浏览器通过这个头告诉服务器,它支持哪种压缩格式。
例如: Accept-Encoding: gzip, deflate
accept-language:浏览器通过这个头告诉服务器,它的语言环境。
例如: Accept-Language: en-us
User-Agent
作用:告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) .....
Authorization:HTTP授权的授权证书
例如:Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control:指定请求和响应遵循的缓存机制
例如:
Cache-Control:Public 可以被任何缓存所缓存()
Cache-Control:Private 内容只缓存到私有缓存中
Cache-Control:no-cache 所有内容都不会被缓存
Cache-Control:max-age=20 到期时间
Cache-Control:'max-age=20, Public' 设置多个值时,用逗号进行分隔
Connection:浏览器通过这个头告诉服务器,请求完后是断开链接还是维持链接。
例如:
Connection: close
Connection:keep-alive 持续链接
Cookie:将cookie的值发送给HTTP 服务器
作用:HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。
referer:浏览器通过这个头告诉服务器,客户机是哪个页面来的(防盗链)。
先前网页的地址,当前请求网页紧随其后,即来路
host:浏览器通过这个头告诉服务器,它想访问哪台主机。
if-modified-since:浏览器通过这个头告诉服务器,缓存数据的时间
(二) HTML <form> 标签的 enctype 属性
enctype 是编码方式的意思
<form enctype="value">
<form enctype="value">
value值:
(1) application/x-www-form-urlencoded 在发送前编码所有字符(默认)
(2) multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
(3) text/plain 空格转换为 "+" 加号,但不对特殊字符编码。
(三) Cookie
Cookie 是服务器保存在浏览器的一小段文本信息,每个 Cookie 的大小一般不能超过4KB。浏览器每次向服务器发出请求,就会自动附上这段信息。
- cookie是服务器保存在浏览器上的一段文本信息
- 大小一般不能超过4kb
- 浏览器向服务器发送请求时,会自动附上这段文本信息
作用:
cookie主要用来区分两个请求是否来自同一个浏览器 ,以及保存一些状态信息。
常用场合:
- 对话(session)管理:保存登录、购物车等需要记录的信息。
- 个性化:保存用户的偏好,比如网页的字体大小、背景色等等。
- 追踪:记录和分析用户行为。
cookie包含的信息:
- Cookie 的名字
- Cookie 的值(真正的数据写在这里面)
- 到期时间
- 所属域名(默认是当前域名)
- 生效的路径(默认是当前网址)
Cookie 对该域名的根路径和它的所有子路径都有效。
用户访问网址www.example.com,果路径设为/forums,那么这个 Cookie 只有在访问www.example.com/forums及其子路径时才有效。以后,浏览器一旦访问这个路径,浏览器就会附上这段 Cookie 发送给服务器。
- 浏览器的同源政策规定,两个网址只要域名相同和端口相同,就可以共享 Cookie
- 注意,这里不要求协议相同。
也就是说,http://example.com设置的 Cookie,可以被https://example.com读取。 只要两个网址的域名和端口号相同(协议可以不同),就可以共享cookie
浏览器可以设置不接受 Cookie,也可以设置不向服务器发送 Cookie。
- 浏览器可以设置不接收cookie
- 浏览器也可以设置不向服务器发送cookie
window.navigator.cookieEnabled属性
- window.navigator.cookieEnabled属性返回一个布尔值,表示浏览器是否打开 Cookie 功能。
浏览器是否打开 Cookie 功能
window.navigator.cookieEnabled // true
document.cookie属性
- document.cookie属性返回当前网页的 Cookie。
当前网页的 Cookie
document.cookie
Cookie 由 HTTP 协议生成,也主要是供 HTTP 协议使用。
(1) HTTP 回应:Cookie 的生成
服务器如果希望在浏览器保存 Cookie,就要在 HTTP 回应的头信息里面,放置一个Set-Cookie字段。
- 服务器在 http响应头 中放置 Set-Cookie 字段,就能在浏览器上保存cookie
- HTTP 回应可以包含多个Set-Cookie字段,即在浏览器生成多个 Cookie
- 除了 Cookie 的值,Set-Cookie字段还可以附加 Cookie 的属性。
- 一个Set-Cookie字段里面,可以同时包括多个属性,没有次序的要求。
- 如果服务器想改变一个早先设置的 Cookie,必须同时满足四个条件:Cookie 的key、domain、path和secure都匹配。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco ----------- 键值对,cookie名:yummy_cookie, 值:choco
Set-Cookie: tasty_cookie=strawberry
[page content]
除了 Cookie 的值,Set-Cookie字段还可以附加 Cookie 的属性
Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<non-zero-digit>
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
一个Set-Cookie字段里面,可以同时包括多个属性,没有次序的要求。
Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly
- 如果服务器想改变一个早先设置的 Cookie,必须同时满足四个条件:Cookie 的key、domain、path和secure都匹配。
在key,domain,path,secure都相同时,服务器才可以改变一个已经设置的cookie,而不是新建一个同名cookie
只要有一个属性不同,就会生成一个全新的 Cookie,而不是替换掉原来那个 Cookie。
Set-Cookie: key1=value1; domain=example.com; path=/blog
----------------------------服务器要改变早先设置的cookie,需要 key domain path secure都相同,如下
Set-Cookie: key1=value2; domain=example.com; path=/blog
(2) HTTP 请求:Cookie 的发送
浏览器向服务器发送 HTTP 请求时,每个请求都会带上相应的 Cookie。也就是说,把服务器早前保存在浏览器的这段信息,再发回服务器。这时要使用 HTTP 头信息的Cookie字段。
- Cookie字段可以包含多个 Cookie,使用分号(;)分隔。
Cookie: foo=bar
上面代码会向服务器发送名为foo的 Cookie,值为bar。
- Cookie字段可以包含多个 Cookie,使用分号(;)分隔。
Cookie: name=value; name2=value2; name3=value3
例子:
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
- 服务器收到浏览器发来的 Cookie 时,有两点是无法知道的。
1. Cookie 的各种属性,比如何时过期。
2. 哪个域名设置的 Cookie,到底是一级域名设的,还是某一个二级域名设的。
(3) Cookie 的属性
- expires: 到期
- 如果不设置expires属性,或者设为null,Cookie 只在当前会话(session)有效,浏览器窗口一旦关闭,当前 Session 结束,该 Cookie 就会被删除。
另外,浏览器根据本地时间,决定 Cookie 是否过期,由于本地时间是不精确的,所以没有办法保证 Cookie 一定会在服务器指定的时间过期。 如果同时指定了Expires和Max-Age,那么Max-Age的值将优先生效。
如果Set-Cookie字段没有指定Expires或Max-Age属性,那么这个 Cookie 就是 Session Cookie,即它只在本次对话存在,一旦用户关闭浏览器,浏览器就不会再保留这个 Cookie。
Expires ------------------------ 到期时间,时间点
Expires属性指定一个具体的到期时间,到了指定时间以后,浏览器就不再保留这个 Cookie。它的值是 UTC 格式,可以使用Date.prototype.toUTCString()进行格式转换。
Max-Age ----------------------- 到期时间,时间段
Max-Age属性指定从现在开始 Cookie 存在的秒数
Domain ------------------------- 域名
Domain属性指定浏览器发出 HTTP 请求时,哪些域名要附带这个 Cookie。
如果没有指定该属性,浏览器会默认将其设为当前 URL 的一级域名,
比如www.example.com会设为example.com,而且以后如果访问example.com的任何子域名,HTTP 请求也会带上这个 Cookie。
如果服务器在Set-Cookie字段指定的域名,不属于当前域名,浏览器会拒绝这个 Cookie。
Path ----------------------------- 路径
Path属性指定浏览器发出 HTTP 请求时,哪些路径要附带这个 Cookie。
- 只要浏览器发现,Path属性是 HTTP 请求路径的开头一部分,就会在头信息里面带上这个 Cookie。比如,PATH属性是/,那么请求/docs路径也会包含该 Cookie。当然,前提是域名必须一致。
Secure --------------- 在https协议时,发送cookie
Secure属性指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。
- secure:是安全的意思
- 另一方面,如果当前协议是 HTTP,浏览器会自动忽略服务器发来的Secure属性。-
- 该属性只是一个开关,不需要指定值。如果通信是 HTTPS 协议,该开关自动打开。
HttpOnly ------------- 指定cookie无法通过脚本拿到
HttpOnly属性指定该 Cookie 无法通过 JavaScript 脚本拿到,主要是Document.cookie属性、XMLHttpRequest对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie。
- document.cookie属性
- XMLHttpRequest对象
- Request API
如何回应头设置HttpOnly,三个都拿不到cookie
document.cookie --------- 读写当前网页cookie
读出全部cookie,写入一个cookie
document.cookie属性用于读写当前网页的 Cookie
document.cookie属性是可写的,可以通过它为当前网站添加 Cookie。
- 读取的时候,它会返回当前网页的所有 Cookie,前提是该 Cookie 不能有HTTPOnly属性,它们之间使用分号分隔。
- 写入的时候,Cookie 的值必须写成key=value的形式。
注意( 值的 )等号两边不能有空格。
- 另外,写入 Cookie 的时候,必须对分号、逗号和空格进行转义(它们都不允许作为 Cookie 的值),这可以用encodeURIComponent方法达到。
- 写入 Cookie 的时候,可以一起写入 Cookie 的属性。
document.cookie一次只能写入一个 Cookie,而且写入并不是覆盖,而是添加。
document.cookie读写行为的差异(一次可以读出全部 Cookie,但是只能写入一个 Cookie )
document.cookie = 'test1=hello'; ------- 值中的 = 之间不能有空格
document.cookie = 'test2=world'; ------- 写cookie时,只能一个个写入
document.cookie ------- 读cookie时,读取所有cookie
// test1=hello;test2=world
- document.cookie读写行为的差异(一次可以读出全部 Cookie,但是只能写入一个 Cookie),与 HTTP 协议的 Cookie 通信格式有关。
- 浏览器向服务器发送 Cookie 的时候,Cookie字段是使用一行将所有 Cookie 全部发送;
- 服务器向浏览器设置 Cookie 的时候,Set-Cookie字段是一行设置一个 Cookie。
属性的写入注意点:
- path属性必须为绝对路径,默认为当前路径。
- domain属性值必须是当前发送 Cookie 的域名的一部分。比如,当前域名是example.com,就不能将其设为foo.com。该属性默认为当前的一级域名(不含二级域名)。
- max-age属性的值为秒数。
- expires属性的值为 UTC 格式,可以使用Date.prototype.toUTCString()进行日期格式转换。
Cookie 的属性一旦设置完成,就没有办法读取这些属性的值。
删除一个现存 Cookie 的唯一方法,是设置它的expires属性为一个过去的日期。
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
上面代码中,名为fontSize的 Cookie 的值为空,过期时间设为1970年1月1月零点,就等同于删除了这个 Cookie。
async函数
async函数是generator函数的语法糖。async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
async:是异步的意思
async函数对 Generator 函数的改进,体现在以下四点。
(1) 内置执行器
Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
- async函数自带执行器,和普通函数一样的方法调用
(2) 更好的语义
async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
- async 表示函数中有异步操作
- await 表示紧跟在await后面的表达式需要等待结果
(3) 更广的适用性
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时等同于同步操作)。
- await命令后面,可以是Promise对象,和原始类型的值
(4) 返回值是 Promise -------------------------- ( 重要 )
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
- async函数返回的是promise对象,可以使用 then 方法指定下一步操作
基本用法:
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
- async返回的是promise对象,async函数内部return语句返回的值,会成为then方法回调函数的参数。
async function f() {
return 'hello world'; ------- 在async函数中,return语句返回的值,会作为 then方法回调函数的参数
}
f().then(v => console.log(v))
// "hello world"
上面代码中,函数f内部return命令返回的值,会被then方法回调函数接收到。
Promise 对象的状态变化
async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
- async函数返回的promise对象,必须等到所有await后的promise对象执行完,才会发生状态改变
即:只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数
----------------------- ( 重要 )
async function getTitle(url) {
let response = await fetch(url);
let html = await response.text();
return html.match(/<title>([\s\S]+)<\/title>/i)[1];
}
getTitle('https://tc39.github.io/ecma262/').then(console.log)
// "ECMAScript 2017 Language Specification"
上面代码中,函数getTitle内部有三个操作:抓取网页、取出文本、匹配页面标题。
只有这三个操作全部完成,才会执行then方法里面的console.log。
await 命令
正常情况下,await命令后面是一个 Promise 对象。
如果不是,会被转成一个立即resolve的 Promise 对象。
- await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。
async function f() {
return await 123;
}
f().then(v => console.log(v))
// 123
上面代码中,await命令的参数是数值123,它被转成 Promise 对象,并立即resolve
- 只要一个await语句后面的 Promise 变为reject,那么整个async函数都会中断执行。
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); // 不会执行
}
上面代码中,第二个await语句是不会执行的,因为第一个await语句状态变成了reject。
- 有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。
这时可以将第一个await放在try...catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// hello world
实例:
import React from 'react';
export default class Func extends React.Component {
componentDidMount() {
async function getName() {
let i = 0;
setInterval(() => {
i = i+1;
console.log(i)
}, 1000); // 每秒输出1,2,3,4,5...
const a = await new Promise(resolve => setTimeout(() => resolve(22222), 2000));
console.log(a); // 2秒后输出22222
const b = await new Promise(resolve => setTimeout(() => resolve(1), 2000));
console.log(b) // 再过两秒输出 1
const c = await new Promise(resolve => setTimeout(() => resolve(a+b), 2000));
return c;
};
getName().then(res => console.log(res, 'res')) // 一共6秒后输出 22223
}
render() {
return (
<div> function scope test </div>
);
}
}
-------------------------- 异步方法同步执行 -------------------------、