美文网首页
面试题【Day04】

面试题【Day04】

作者: 小王子__ | 来源:发表于2021-08-24 11:35 被阅读0次

    本篇绪论

    • 1,get请求传参的误区,get、post请求在缓存方面的区别
    • 2, setTimeout、promise、async/await区别
    • 3, 小程序跳转另一个小程序
    1,get请求传参的误区,get、post请求在缓存方面的区别

    实际上HTTP协议从未规定get/post请求长度限制是多少,对get请求参数的限制是浏览器或者web服务器,浏览器或web服务器限制了url的长度。不同的浏览器和web服务器限制的长度不一样

    get、post请求在缓存方面的区别:

    • get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
    • post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存
    2, setTimeout、promise、async/await区别

    首先看道面试题

    async function async1() {
        console.log('async1 start')
        await async2()
        console.log('async1 end')
    }
    async function async2() {
        console.log('async2')
    }
    console.log('script start')
    setTimeout(function () {
        console.log('settimeout')
    })
    async1()
    new Promise(function (resolve) {
        console.log('promise1')
        resolve()
    }).then(function () {
        console.log('promise2')
    })
    console.log('script end')
    

    题目的本质是考察setTimeout、promise、async/await的实现及执行顺序,以及JS的事件循环的相关问题。

    答案

    再看一个经典的例子

    const p = Promise.resolve()
    (async () => {
        await p
        console.log('await end')
    })()
    p.then(() => {
        console.log('then 1')
    }).then(() => {
        console.log('then 2')
    })
    
    image

    这里涉及到微任务、宏任务、event loop以及JS的异步运行机制

    Event loop

    JS主线程不断的循环往复的从任务队列中读取任务,执行任务,其中运行机制称为事件循环(Event loop)

    宏任务、微任务

    宿主(如浏览器)发起的任务称为宏观任务,JS引擎发起的任务称为微观任务。

    宏任务大概包括:

    • 定时器:setTimeout、setInterval、setImmediate
    • I/O操作:比如读写文件
    • 消息通道:MessageChannel
    • script整体代码

    微任务大概包括:

    • promise.then
    • async/await(等价于promise.then)
    异步运行机制

    因为JS是单线程的,JS主线程拥有一个执行栈(同步任务)和一个任务队列,主线程会依次执行代码。

    • 当遇到函数(同步)时,会先将函数入栈,函数运行结束后再将该函数出栈
    • 当遇到 task 任务(异步)时,这些 task 会返回一个值,让主线程不在此阻塞,使主线程继续执行下去,而真正的 task 任务将交给 浏览器内核 执行,浏览器内核执行结束后,会将该任务事先定义好的回调函数加入相应的任务队列(microtasks queue(微任务队列)/ macrotasks queue(宏任务队列))中
    • 当JS主线程清空执行栈之后,会按先入先出的顺序读取microtasks queue中的回调函数,并将该函数入栈,继续运行执行栈,直到清空执行栈,再去读取任务队列。
    • 当microtasks queue中的任务执行完成后,会提取 macrotask queue 的一个任务加入 microtask queue, 接着继续执行microtask queue,依次执行下去直至所有任务执行结束。
    // 1,开始执行
    console.log(1) // 2,打印 1
    setTimeout(function () {   // 6,浏览器在0s后,将该函数推入任务队列
        console.log(2)  // 7,打印 2
        Promise.resolve(10).then(function () {  // 8,将resolve(10)推入到任务队列。// 9,将function函数推入任务队列
            console.log('ok')  // 10,打印 ok
        })
    })  // 3,调用setTimeout函数,并定义其完成之后执行的回调函数
    setTimeout(function (){
        console.log(3)
    })  // 4,调用setTimeout函数,并定义其完成后执行的回调函数
    // 5,主线程执行栈清空,开始读取任务队列中的任务
    

    setTimeout:

    console.log(111)  // 1, 打印 111
    setTimeout(function () { // 4,打印 setTimeout
      console.log('setTimeout')
    })  // 2,调用setTimeout函数,并定义其完成后执行的回调函数
    console.log(222) // 3,打印 222
    

    Promise:

    promise本身是同步的立即执行函数,当在执行resolve或reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会去调用resolve/reject中存放的方法执行

    console.log('script start')
    let promise1 = new Promise(function (resolve) {
        console.log('promise1')
        resolve()
        console.log('promise1 end')
    }).then(function () {
        console.log('promise2')
    })
    setTimeout(function(){
        console.log('settimeout')
    })
    console.log('script end')
    
    image
    const p = Promise.resolve() // 1, p 的状态是 reslove
    (async () => {  
        await p  // 2,返回,并将函数后面的语句console.log('await end')放入下一个事件循环的微任务中
        console.log('await end')  // 6,执行,打印 await end
    })()
    p.then(() => {  // 3,p的状态为resolve,会把p.then()放入当前事件循环的微任务中
        console.log('then 1') // 4,执行,打印 then 1
    }).then(() => {
        console.log('then 2')  // 5,执行,打印 then 2 当前微任务结束,运行下一个微任务
    })
    

    以上输出结果为:then 1 => then 2 => await end

    async/await
    async function async1(){
      console.log('async1 start');
      await async2();
      console.log('async1 end')
    }
    async function async2(){
      console.log('async2')
    }
    
    console.log('script start');
    async1();
    console.log('script end')
    

    async函数返回一个promise对象,当函数执行的时候,一旦遇到await就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出async函数体。


    image
    async function fun () {
      return 1
    }
    console.log(fun())
    
    image

    很显然,fun的运行结果其实就是一个promise对象,因此我们可以使用then来处理后续逻辑

    fun().then(res => {
      console.log(res)  // 1
    })
    

    await的含义为等待,也就是async函数需要等待await后的函数执行完成并且有了返回结果(promise对象)之后,才能继续执行下面的代码。await通过返回一个Promise对象来实现同步的效果。

    3,小程序跳转另一个小程序
    wx.navigateToMiniProgram({
          appId: 'xxx', // 必填
          path: 'pages/index/index', // 如果为空,则打开首页 path中?后面的部分回传成为query,在小程序的App.onLaunch、App.onShow和Page.onLoad的毁掉函数中可以获取到query参数
          extraData: {  // 非必填,需要传递给目标小程序的数据,目标小程序可在 App.onLaunch,App.onShow 中获取到这份数据
            platform: 1
          },
          envVersion: 'release', // 非必填 要打开的小程序版本。仅在当前小程序为开发版或体验版时此参数有效。如果当前小程序是正式版,则打开的小程序必定是正式版。
          success(res) {
          }
        })
    

    object.envVersion 的合法值

    • develop 开发版
    • trial 体验版
    • release 正式版

    相关文章

      网友评论

          本文标题:面试题【Day04】

          本文链接:https://www.haomeiwen.com/subject/xwldiltx.html