JS基础 异步

273 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

异步和单线程

  • JS 是单线程语言,只能同时做一件事
  • 浏览器和 nodejs 以支持 JS 启动进程,如 Web Worker
  • JS 和 DOM 渲染共用同一个线程,因为 JS 可修改 DOM 结构
  • 遇到等待(网络请求,定时任务)不能卡住
  • 异步是通过 callback 函数形式来调用
// 异步
console.log(100)
setTimeout(function () { // callback 回调函数
    console.log(200)
}, 1000)
console.log(300)


// 同步
console.log(100)
alert(200)
console.log(300)

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

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

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

  • 网络请求,如 ajax 图片加载
  • 定时任务,如 setTimeout
// ajax
console.log('start')
$.get('./data1.json', function (data1) {
    console.log(data1)
})
cosnole.log('end')


// 定时器
console.log(100)
setInterval(function () {
    console.log(200)
}, 1000)
console.log(300)

Promise

promise 出现前的 callback hell(回调地狱)

// 获取第一份数据
$.get(url1, (data1) => {
    console.log(data1)
    
    // 获取第二份数据
    $.get(url2, (data2) => {
        console.log(data2)
        
        // 获取第三份数据
        $.get(url3, (data3) => {
            console.log(data3)
            
            // 还可能获取更多的数据
        })
    })
})

使用 promise 解决回调地狱

const url1 = '/data1.json'
const url2 = '/data2.json'
const url3 = '/data3.json'

getData(url1).then(data1 => {
    console.log(data1)
    return getData(url2)
}).then(data2 => {
    console.log(data2)
    return getData(url3)
}).then(data3 => {
    console.log(data3)
}).catch(err => console.error(err))

手写用 Promise 加载一张图片

const url = 'https://img.mukewang.com/124.jpg'

function loadImg(src) {
    return new Promise((resolve, reject) => {
        const img = ducument.createElement('img')
        img.onload = () => {
            resolve(img)
        }
        img.onerror = () => {
            const err = new Error(`图片加载失败 ${src}`)
            reject(err)
        }
        img.src = src
    })
}

loadImg(url).then(img => {
    console.log(img.width)
    return img
}).then(img => {
    console.log(img.height)
}).catch(ex => console.error(ex))

题目:代码中打印的顺序是什么?

console.log(1)
setTimeout(function () {
    console.log(2)
}, 1000)
console.log(3)
setTimeout(function () {
    console.log(4)
}, 0)
console.log(5)