前端的同步异步和promise、async、await的使用
同步和异步为什么js分同步和异步?同步JavaScript是一门单线程的语言,因此,JavaScript在同一个时间只能做一件事,单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务,会造成运行阻塞,严重的话会造成页面长时间无响应,js执行时间过长等异步异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,...
同步和异步
为什么js分同步和异步?
同步
JavaScript是一门单线程的语言,因此,JavaScript在同一个时间只能做一件事,单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务,会造成运行阻塞,严重的话会造成页面长时间无响应,js执行时间过长等
异步
异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务
定时器、ajax请求、异步函数都是异步,获取异步代码的执行结果能通过回调函数来接受
在js中,所有的异步回调函数执行一定在普通代码之后
总的来说,JavaScript的异步机制包括以下几个步骤
(1)所有同步任务都在主线程上执行,行成一个执行栈
(2)主线程之外,还存在一个任务队列,只要异步任务有了结果,就会在任务队列中放置一个事件
(3)一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面还有哪些事件,那些对应的异步任务结束等待状态,进入执行栈,开始执行
(4)主线程不断的重复上面的第三步
// 封装一个请求函数 输入一个地址 返回一个请求结果
request('请求路径',回调函数function (形参) { // 调用函数
// console.log(形参)
})
function request(url,callback) {
let xhr = new XMLHttpRequest(); // 创建异步对象
xhr.open(url,'GET');
xhr.send();
oReq.addEventListener("load", function () {
// 当请求成功了,也就是异步执行结束了,callback 被调用了
// 我调用的时候,给 callback 传递了一个参数
callback(this.responseText)
// 只有这里才能拿到正确的响应结果 responseText
// return this.responseText
});
}
异步串行
callback hell 回调地狱
当一段代码在请求返回结果后需要立即执行,就需要异步串行。在以前写代码需要再请求结果再次发出请求,就会回调地狱。如下图:
Promise优化callback hell
Promise是ES6新增的一个构造函数,是一个返回对象,解决异步编程的一种方案,简化异步代码,让其更容易阅读,更易维护
promise的基本使用
function request(time) {
// 创建一个promise对象 传递一个函数参数
return const p1 = new Promise(function (resolve,reject) { // 参数1:resolve函数(成功) 参数2:reject函数(失败)
// 在函数中执行一个异步操作
setTimeout(() => {
resolve() // 异步完成后执行该函数 函数会调用p1.then的第一个参数
reject() // 失败执行该函数
},time)
})
}
// 获取执行效果
request(1000).then(() => { // 成功执行 then方法的参数1就是resolve函数 then方法执行完成后会返回一个新的Promise对象
// 输出
},() => { // 失败执行
// 输出
})
封装一个异步函数
request('http://jsonplaceholder.typicode.com/posts') //调用
.then(data => { // 调用的是成功的方法
console.log('请求成功', data) // then方法执行完成后会返回一个新的poromise对象
// return new Promise((resolve) => {
// resolve()
// })
})
.catch(err => { // 调用的是失败的方法
console.log('请求失败', err)
})
.finally(() => {
console.log('无论成功或是失败都会执行')
})
// 1. 定义函数
function request(url) {
// 2、在函数中 return 出一个 Promise 对象
return new Promise((resolve, reject) => {
// 3、在 Promise 容器中执行异步操作
// 4、异步操作
// 成功:resolve
// 失败:reject
// 创建请求对象
var oReq = new XMLHttpRequest();
// 添加请求回调函数
// 请求成功,就会自动执行该回调函数
oReq.addEventListener("load", function () {
// 当请求成功了,也就是异步执行结束了,callback 被调用了
// 我调用的时候,给 callback 传递了一个参数
// callback(this.responseText)
// 如果没有数据
// resolve()
// 如果有数据
resolve(this.responseText)
});
// 请求失败,就会自动执行该回调函数
oReq.addEventListener("error", function (err) {
// 失败 reject
reject(err)
});
// 设置请求方法和请求路径
oReq.open("GET", url);
// 发出请求
oReq.send();
})
}
Async-await 函数简化获取Promise的结果,本质还是promise
某个方法的返回如果是promise对象,可以用async await来优化
任何函数都可以使用async,获取async函数的返回值,await只能在标记了async的函数中
使用,async函数中始终返回的是promise对象
// 具名函数:async function main() {
// 匿名函数:async function () {}
// 箭头函数:async () => {}
// 对象函数成员简写:
// const user = {
// sayHello: async function () {}
// async sayHello () {}
// sayHello: async () => {}
// }
async function main() {
retuen 1 // 如果是普通数据则包装成promise对象,数据就是resolve的结果
await // await简化了获取promise结果 await只能在标记了async的函数中使用
}
// 通过.then方法来获取async函数的返回值
const ret = main()
ret.then((data) => {
console.log(data)
})
// 在另一个函数中获取async函数的值
async function main2() {
const datas = await main() // await后跟promise才有意义
console.log(datas)
}
async函数的异常处理
async function main() {
try 捕获异常 {
const data = await request('url') //await只能获取promise对象的请求成功结果
}cathc (err) {
console.log('请求失败了')
}
}
async-await的获取
async function main() {
const data = await request('url') // await 获取promise的成功结果 await只能在被async标记了的函数中使用
}
function request(url) {
// 创建一个promise对象并返回,传递一个匿名函数
return new Promise((resolve,reject) => { // 匿名函数有形参 resolve 成功 reject 失败
let xhr = new XMLHttpRequest() // 创建一个异步对象
xhr.open("GET",url) // 设置请求路径和方法
xhr.send() // 发送请求
xhr.addEventListener('load',function() { // 响应成功自动执行
resolve(this.responseText) // resolve就是调用了then函数
})
xhr.addEventListener('error',function(err) { // 响应失败自动执行
reject(err)
})
})
}
更多推荐
所有评论(0)