单线程和异步有何关系
- 单线程:只有一个线程,只能做一件事
- 原因:避免DOM渲染冲突
(1)浏览器需要渲染DOM
(2)JS可以修改DOM结构
(3)JS执行的时候,浏览器DOM渲染会暂停
(4)两段JS也不能同时执行(都修改DOM就冲突了)
(5)HTML5中webworker支持多线程,但不能访问DOM(应用不广泛)
- 解决方案:异步(先让其他代码先执行,异步执行的后面执行)
console.log(100)
$.ajax({
url: 'xxx',
success: function (result) { // ajax加载完才执行
console.log(result) // 先不管它,先让其他JS代码运行
}
})
console.log(300)
console.log(400)问题:
(1)没有按照书写方式执行,可读性差
(2)callback中不容易模块化(异步之后需要执行的函数)
event-loop(事件循环/事件轮询)
- 什么是event-loop(JS实现异步的具体解决方案)
(1)同步代码,直接执行
(2)异步函数先放在异步队列中
(3)待同步函数执行完毕,轮询执行异步队列的函数(像有个哨兵一直进行监视,异步队列中一有函数就开始执行)
- 实例分析
setTimeout(function () {
console.log(100)
})
console.log(200)
// 主进程
console.log(200)
// 异步队列
function () {
console.log(100)
}setTimeout(function () {
console.log(1)
}, 100)
setTimeout(function () {
console.log(2)
})
console.log(3)
// 主进程
console.log(3)
// 异步队列
// 立即加入
function () {
console.log(2)
}
// 100ms 之后被放入
function () {
console.log(1)
}- 实战
目前JS解决异步的方案有哪些
如果只用jquery如何解决异步(jQuery Deferred)
- 无法改变JS异步和单线程的本质
- 只能从写法上杜绝callback这种写法
- 它是一种语法糖形式,但是解耦了代码
- 很好的体现:开放封闭原则(对扩展开放对修改封闭)
// jQuery1.5之前
var ajax = $.ajax({
url: 'xxx',
success: function() {
// 没有地方进行扩展只能在这里进行修改
},
error: function() {
}
})
console.log(ajax) // 返回一个XHR对象
// jQuery 1.5之后 需要新加代码时可以直接只加个done或者then进行扩展
var ajax = $.ajax('xxx')
ajax.done(function() {
}).fail(function() {
}).done(function() {})
ajax.then(function () {
console.log('success 1')
}, function () {
console.log('error 1')
}).then(function () {
console.log('success 2')
}, function () {
console.log('error 2')
})jQuery Deferred 和 Promise的区别?
(1)jQuery Deferred 有resolve() 、reject()主动触发的函数也有then()、done()、error()被动监听的函数
(2)Promise 只能被动监听 不能主动修改
// 已经封装好的(A 员工)
function waitHandle() {
// 定义
var dtd = $.Deferred()
var wait = function (dtd) {
var task = function () {
console.log('执行完成')
// 成功
dtd.resolve()
// 失败
// dtd.reject()
}
setTimeout(task, 1000)
// wait 返回
return dtd.promise()
}
// 最终返回
return wait(dtd)
}
// 使用(B 员工)
var w = waitHandle() // promise 对象
$.when(w).then(function () {
console.log('ok 1')
}, function () {
console.log('err 1')
})Promise的标准
- 基本语法回顾
function loadImg(src) {
const promise = new Promise(function (resole, reject) {
var img = document.createElement('img')
img.onload = function () {
resolve(img) // 解决
}
img.onerror = function () {
reject() // 拒绝
}
img.src = src
})
return promise
}
var src = '图片地址'
var result = loadImg(src)
result.then(function (img) {
console.log(img.width)
},function () {
console.log(failed)
})
result.then(function (img) {
console.log(img.height)
})- 异常捕获(throw error和reject都可以用)
规定:then只接受一个参数,最后统一用catch捕获异常
- 多个串联
- Promise.all 和 Promise.race
- Promise 标准
(1)三种状态:pending、fulfilled、rejected;初始状态是:pending;pending变为fulfilled,或者pending变成rejected(状态变化不可逆)
(2)Promise 实例必须实现then 这个方法;then()必须可以接受两个函数作为参数;then返回必须是一个Promise实例(没有返回时默认被调用的实例); then只是将callback拆分了
async/await的使用(ES7): 最直接的同步写法
- 使用了Promise,并没喝Promise冲突
- 完全是同步的写法,再也没有回调函数
- 改变不了JS单线程异步的本质