Skip to content

一、异步和单线程

1. 同步和异步的区别是什么?

答案: 同步会阻塞代码执行;异步不会阻塞代码执行。
解析:

  • 什么是单线程?

    • JS是单线程语言,只能同时做一件事。
    • 浏览器和nodejs已支持JS启动进程。
    • JS和DOM渲染共用同一个线程,因为JS可修改DOM结构(JS执行时,DOM停止渲染;DOM渲染时,JS停止执行)
  • 为什么需要异步?(异步时基于callback回调函数形式调用的 )

    • 遇到等待,如网络请求和定时任务时不能卡住
  • 异步和同步的区别?

    • 基于JS是单线程语言
    • 异步不会阻塞代码执行
    • 同步会阻塞代码执行
  • 应用场景

    • 网络请求,如ajax图片加载
      js
          //ajax
          console.log('start');
          $.get('./data1.json', function(data1) {
              console.log(data1);
          })
          console.log('end');
          
          // 图片加载
          console.log('start');
          let img = document.createElement('img')
          img.onload = function() {
              console.log('loaded');
          }
          img.src = './xxx.png'
          console.log('end');
    • 定时任务,如setTimeout、setInterval
      js
            // setTimeout
          console.log(100);
          setTimeout(function() {
              console.log(200);
          }, 1000)
          console.log(300);
          
          
          // setInterval
          console.log(100);
          setInterval(function() {
              console.log(200);
          }, 1000)
          console.log(300);
    • callback hellpromise
      • promise的形式是一个管道式的串联形式,回调函数都放在then中;与传统的嵌套形式不同。
        • 实现Promise的思路

          promise是一个构造函数,其接受一个函数作为参数;作为参数的函数里,有两个方法resolve和reject;promise带有方法then和catch。我们需要调用resovle和reject方法去改变状态, resolve调用意味着异步请求已经有了结果,可以执行then里面的回调了。

        • Promise有哪几种状态?从一种状态到另一种状态还能不能再改变?

          回答:有pending(初始状态)、fulfilled(成功状态)、rejected(失败状态)三种状态。 Promise的含义为承诺,这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了。 pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。 fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then() reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()。

        • Promise的then返回什么?
          • then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定。因此可以使用链式调用解决回调地狱的问题。

2. 手写Promise加载一张图片

  • then中箭头函数的参数img是由resolve传入的
  • then方法中return的返回值会传递到第二个then里
    js
    //promise基本使用
    function loadImg(src) {
      const p = new Promise(
        (resolve, reject) => {
          const img = document.createElement('img')
          img.onload = () => {
            resolve(img) //img参数由then接收
          }
          img.onerror = () => {
            const err = new Error(`图片加载失败${src}`)
            reject(err)
          }
          img.src = src
        }
      )
      return p
    }
    
    const url = 'https://picnew7.photophoto.cn/20130416/dahaishatanhaidaotupian-11521953_1.jpg'
    
    loadImg(url).then(img => {
      console.log(img.width);
      return img //这个return会传到第二个then里
    }).then(img => {
      console.log(img.height);
    }).catch(ex => console.error(ex))
  • 链式引用promise,解决回调地狱问题
    js
      function loadImg(src) {
        const p = new Promise(
          (resolve, reject) => {
            const img = document.createElement('img')
            img.onload = () => {
              resolve(img) //img参数由then接收
            }
            img.onerror = () => {
              const err = new Error(`图片加载失败${src}`)
              reject(err)
            }
            img.src = src
          }
        )
        return p
      }
      
      // 怎么使用串行方式解决回调地狱?
      const url1 = 'https://picnew7.photophoto.cn/20130416/dahaishatanhaidaotupian-11521953_1.jpg'
      const url2 = 'https://static2.cbrimages.com/wordpress/wp-content/uploads/2021/04/luffy-feature-image.jpg'
      
      loadImg(url1).then(img1 => {
          console.log(img1.width);
          return img1 //普通对象
      }).then(img1 => {
          console.log(img1.height);
          return loadImg(url2) //promise实例
      }).then(img2 => {
          console.log(img2.width);
      return img2
      }).then(img2 => {
          console.log(img2.height);
      }).catch(ex => console.error(ex))

3. 前端使用异步的场景有哪些?

答案: 网络请求,如ajax图片加载;定时任务,如setTimeout、setInterval。

Released under the MIT License.