同步和异步

​ 为什么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)
            })
        }) 
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐