美文网首页
面试题【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