在工作和面试中,基础知识必须牢固,今天开始,不仅要继续读源码类知识,还要复习基础知识。
1. 什么是单线程,和异步有什么关系?
1.1 单线程
单线程 - 只有一个线程,同一时间只能做一件事。
console.log(100)
setTimeout(() => {
console.log(200)
}, 1000)
console.log(300)
console.log(400)
1.2 原因
原因 - 避免DOM渲染的冲突。
详细解释:浏览器需要修改DOM,JS可以修改DOM,JS执行的时候,浏览器DOM渲染会暂停。两段JS也不能同时执行,都修改DOM就冲突了。
webworker支持多线程,但是不能访问DOM。
1.3 异步
解决方案 - 异步。
问题一:没按照书写方式执行,可读性差。
问题二:callback不容易模块化。(后期维护代码不好排查问题)
1.4 解答
单线程就是同时只做一件事,两段JS代码不能同时执行。
原因就是为了避免DOM渲染的冲突。
异步是单线程的解决方案,但是也存在相应的问题。
2. 什么是event-loop?
事件轮询,JS实现异步的具体解决方案。
同步代码,直接执行。
异步函数先放在异步队列中。
待同步函数执行完毕,轮询执行异步队列的函数。
涉及到宏任务和微任务的知识,可以参考网上的博客。
3. jquery的Deferred
var ajax = $.ajax('data.json')
ajax.then(function () {
// 成功
}, function () {
// 失败
})
.then(function () {
// 成功
}, function () {
// 失败
})
// 或者
ajax.done(function () {
console.log('success')
}).fail(function () {
console.log('fail')
}).done(function () {
console.log('success2')
}).done(function () {
console.log('success3')
})
使用jQuery Deferred
function handleWait () {
var dtd = $.Deferred() // 创建Deferred实例
var wait = function (dtd) {
var task = function () {
console.log('执行完成')
dtd.resolve() // 成功
// dtd.reject() // 失败
}
setTimeout(task, 1000)
return dtd.promise() // 加promise的原因是防止外面修改resolve或者reject状态
}
return wait(dtd)
}
// 返回的promise对象后需要$.when处理一下
var result = handleWait()
$.when(result).then(function () {
console.log('success 1')
}, function () {
console.log('error 1')
})
// 但是reject的时候,不能写成链式操作,需要拆开写
$.when(result).then(function () {
console.log('success 1')
}, function () {
console.log('error 1')
})
$.when(result).then(function () {
console.log('success 2')
}, function () {
console.log('error 2')
})
4. Promise的基本使用和原理
4.1 基本语法
基本语法在ES6中已经介绍过,这里就忽略了。
4.2 异常捕获
无论有多少个then,统一用catch捕获异常
result.then(function () {
// 成功
}).then(function () {
// 成功
}).catch(function (err) {
// 捕获异常
})
4.3 多个串联
可以通过第一个then返回一个promise对象,实行串联。
function loadText (src) {
return new Promise((resolve, reject) => {
$.ajax({
url: src,
success: function (data) {
resolve(data)
},
fail: function (err) {
reject(err)
}
})
})
}
var src1 = './data.txt'
var result1 = loadText(src1)
var src2 = './data2.txt'
var result2 = loadText(src2)
result1.then(function (data) {
console.log('data1' + data)
return result2
}).then(function (data) {
console.log('data2' + data)
})
4.4 Promise.all Promise.race
Promise.all接受一个promise对象数组,待全部完成后统一执行then中的success,then中接受的参数是一个数组,里面是所有的返回内容
Promise.all([result1, result2]).then((datas) => {
console.log(datas)
})
Promise.race接受一个promise对象数组,只要有一个完成就执行then中的success,then中接受的参数是最先返回的内容
Promise.race([result1, result2]).then((data) => {
console.log(data)
})
4.5 Promise状态
初始状态: pending
成功:fulfilled
失败:rejected
5. 介绍一下async/await(和Promise的区别、联系)
async/await是最直接的同步写法
5.1 基本语法
function loadText (src) {
return new Promise((resolve, reject) => {
$.ajax({
url: src,
success: function (data) {
resolve(data)
},
error: function (err) {
reject(err)
}
})
})
}
async function handleLoadText () {
let result1 = await loadText('./data.txt')
console.log(result1)
let result2 = await loadText('./data2.txt')
console.log(result2)
}
handleLoadText()
5.2 解答
使用了Promise,并没有和Promise冲突
完全是同步的写法,再也没有回调函数
6. 总结当前JS解决异步的方案
jquery Deferred
promise
async await
generator