【1】async/await
用红宝书上的话说,"async/await" 其实就是异步函数
,是 Promise 在函数中的应用, ES8(ES2017)中新增的规范。这个新增的特性能够让以 同步方式
写的代码能够 异步执行
,让整个逻辑更扁平化,更直观易读。
换句话说,async函数完全可以看作多个异步操作,包装成的一个Promise对象,允许在函数内部使用await,而 await命令就是内部then命令的语法糖。
- async 函数返回的是一个Promise对象,会自动包装一个 promise,用于返回指定的值;
- await 只能在 async 函数中使用,await 相当于 Promise 的 then;
- 多个await命令的异步操作,如果不存在依赖关系(后面的await不依赖前一个await返回的结果),用
Promise.all()
让它们同时触发; - async 函数就是 Generator函数 的语法糖;
let [res1, res2] = await Promise.all([test1(), test2()]);
// 如果不存在继发关系,最好让它们同时触发
// `let [val1, val2] = await Promise.all([test1(), test2()]);`
async function main() {
try { // 可捕获异常
var val1 = await firstStep();
var val2 = await secondStep(val1);
var val3 = await thirdStep(val1, val2);
console.log('Final: ', val3);
} catch (err) { // 如有异常,catch 进行处理
console.error(err);
}
}
async/await执行顺序
await 后面的函数执行完毕时,await 会产生一个微任务(Promise.then是微任务)。
console.log('script start')
// 执行async1(),会调用async2(),然后输出async2 end,此时将会 “保留async1函数的上下文”,然后跳出async1函数,让出线程
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() { console.log('async2 end') }
async1()
// 遇到setTimeout,产生下一轮宏任务
setTimeout(function() { console.log('setTimeout') }, 0)
// 执行Promise,输出Promise。遇到resolve,其后的then,会产生第一个微任务队列
new Promise(resolve => {
console.log('Promise')
resolve()
}).then(function() { console.log('promise1') }).then(function() {
console.log('promise2')
})
// 正常输出script end
console.log('script end')
/*
* 此时,此次Event Loop宏任务((当前宏任务)都执行完了。开始执行当前宏任务产生的微任务队列,
* 因为async2函数是async关键词修饰,因此,将await async2后的代码扔到微任务队列中,输出promise1
*
* script start => async2 end => Promise => script end => async1 end => promise1 => promise2 => setTimeout
*/
【2】Promise
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。构造函数(() => {}
),接收两个参数,resolve 和 reject,用于生成Promise 实例,适合等待多个任务顺序执行的操作。
Promise 是一个构造函数(函数也是对象),用于生成 Promise 实例,是对 一个异步操作的封装
,它可以获取异步操作的消息,异步操作里有等待完成(pending)、成功(resolved -> fulfilled) 和 失败(rejected)
三种可能的结果,对应了 Promise 对象的三种状态。一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise 对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。
使用 Promise 对象的好处在于:
- 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
- Promise 对象提供统一的接口,使得控制异步操作更加容易。
缺点:
- 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject,他们的作用分别是将状态修改为 resolved 和 rejected
。
Promise 实例方法:.then( onfulfilled, onrejected ), .catch( onrejected )
,then 方法可以返回一个新的 Promise 实例,所以可以链式调用;Promise 通过 then 回调的方式获取结果,形式上还是有回调地狱
// 1.创建一个新的promise对象,接口封装
const p = new Promise((resolve, reject) => { // 执行回调函数
// 2.执行异步操作任务
setTimeout(() => { // 异步回调函数,会放入队列将来执行
const time = Date.now() // 如果当前时间是偶数就代表成功,否则失败
// 3.1 如果成功,调用resolve(value)
if (time%2 == 0) {
resolve(‘成功的数据, time=’, + time)
} else {
// 3.2 如果失败,调用reject(reason)
reject(‘失败的数据, time=’, + time)
}
},1000)
})
// 业务层的接口调用
p.then( value => { // 接收到成功的value数据的回调 onResolved
console.log(‘成功的回调’, value)
}).catch(reason => { // 状态变为rejected后执行的回调 rejected
console.log(‘失败的回调’, reason)
});
【3】HTTP
HTTP 就是一个用文本格式描述报文头并用双换行分隔报文头和内容,目的是规定客户端和服务端数据传输的格式和数据交互行为,并不负责数据传输的细节,是在TCP基础上实现的请求-响应模式的双向通信协议。默认端口为80
HTTP之 Request
请求行(request line) - 用于说明请求的类型、要访问的资源及使用的HTTP版本
请求头(request head) - 用于说明服务器使用的附加信息
空行
请求数据
HTTP之 Response
状态行 - 由 HTTP版本号(HTTP/1.1),状态码(200) 及 状态消息(OK) 三部分组成
消息报头 - 说明了一些客户端要使用的附加信息
空行
响应正文
HTTP之 工作原理
- 客户端向服务器发送请求报文,请求报文中包含了请求的方法、URL、协议版本、请求头和请求数据。
- 服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头和响应数据。