Appearance
异步编程
单线程
JavaScript 语言和执行环境是单线程。即同一时间,只能处理一个任务。
如果当前正在执行的任务尚未执行完成,它就会阻塞其他正在排队的任务。
为了解决这个问题,JS 在设计之初,将任务分成了两类:同步任务、异步任务。
同步和异步
同步任务:在主线程上排队执行的任务。只有前一个任务执行完毕,才能执行下一个任务。
异步任务:不进入主线程,而是进入任务队列的任务,该任务不会阻塞后面的任务执行。只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
事件循环机制
- 同步任务:进入主线程后,立即执行。
- 异步任务:会先进入 Event Table,等时间到了之后,再进入 Event Queue,进行排队。
- 主线程任务执行完毕:此时主线程处于空闲状态,于是会去读取 Event Queue 中的任务队列,如果有任务,则进入到主线程去执行。
Ajax
Ajax:Asynchronous Javascript And XML(异步 JavaScript 和 XML)。
同源和跨域
同源策略是一个重要的安全策略,主要用来防止 XSS、CSRF 等攻击。
所谓同源是指:域名,协议,端口三者完全相同。
不同源之间的访问请求就叫做跨域。
跨域限制
无法读取 Storage
无法操作 DOM
无法发送 AJAX
如何跨域
生产环境跨域
js// vue.config.js module.exports = { devServer: { port: 8080, proxy: { '/api': { target: 'https://m.maoyan.com', changeOrigin: true, pathRewrite: { '^/api': '' } } } } } // http.js const baseURL = process.env.NODE_ENV == 'development' ? '/api' : 'https://m.maoyan.com'
CORS
CORS 是一个 W3C 标准,全称跨域资源共享
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 除外。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
- Jsonp
Promise
回调函数:把函数 A 传给另一个函数 B 调用,那么函数 A 就是回调函数。
ES6 中的 Promise 是异步编程的一种方案。从语法上讲,Promise 是一个对象,它可以获取异步操作的消息。
- 解决回调地狱的问题(层层嵌套的回调函数)。
- 语法简洁、可读性强,便于后期维护。
- 简洁的 API,使得管理异步操作更加容易。
创建一个 promise 对象,promise 有三种状态:
- 初始化:pending
- 成功:fulfilled
- 失败:rejected
js
let p = new Promise((resolve, reject) => {
// pending
console.log('同步代码')
// 异步代码
if (s) {
// fulfilled
console.log('成功')
resolve(data)
} else {
// rejected
console.log('失败')
reject(data)
}
})
p.then(
(res) => {
// pending => fulfilled 时触发
console.log(res, 'success')
},
(err) => {
// pending => rejected 时触发
console.log(err, 'fail')
}
)
处理 reject 的两种写法
js
let p = new Promise((resolve, reject) => {})
p.then(
(res) => {},
(err) => {}
)
p.then((res) => {}).catch((err) => {})
catch()
可以被 then()
的第二个参数截获而自己捕获不到,就近原则。
总是推荐使用 catch()
进行捕获,而不是 then()
的第二个参数。
catch()
可以捕获到 then()
的第一个参数里的异常,而 then()
的第二个参数捕获不到。
Promise 方法
实例方法:
- promise.then():获取异步任务的正常结果。
- promise.catch():获取异步任务的异常结果。
- promise.finaly():异步任务无论成功与否,都会执行。
静态方法:
Promise.resolve()
Promise.reject()
Promise.all():并发处理多个异步任务,所有都成功,才算成功(resolve);一个失败,整体失败(reject)。
Promise.race()
Promise.allSettled()
并发请求:
js
function getUser() {
return http.get('/user')
}
function getRole() {
return http.get('/role')
}
Promise.all([getUser(), getRole()]).then((res) => {
let user = res[0]
let role = res[1]
})
Async Await
async/await 是在 ES8(即 ES 2017)中引入的新语法,是另外一种异步编程解决方案。
- async 的返回值是 Promise 实例对象。
- await 可以得到异步结果。
我们在使用 Promise、async...await、Generator 的时候,返回的都是 Promise 的实例。
如果直接使用 Promise,则需要通过 then 来进行链式调用;如果使用 async...await、Generator,写起来更像同步的代码。
js
async function init() {
try {
let data = await getData()
} catch (e) {
console.log(e)
}
}