JS异步方案
单线程和event-loop
-
单线程:JS引擎线程只有一个,避免多线程DOM渲染冲突(GUI渲染线程互斥也是同理)
-
异步:解决JS单线程只能同时做一件事的问题,
-
event-loop:主线程从任务队列中读取事件,这个过程是循环不断的,实现异步的具体解决方案
callback
-
代码演示:
$.ajax({ url: 'xxx', success: function(res => { }) })
jquery的deferred
-
概念:jquery1.5版本之后ajax的实现就用的deferred,慢慢演变成promise
-
ajax的变化, 链式操作,对拓展开放,对修改封闭
// 1.5前 var ajax = $.ajax({ url: 'xxx', success: function(res => {}), error: function(err => {}) }) console.log(ajax) // xhr对象 // 1.5后 var ajax = $.ajax('xxx'); // ajax.reject() 可以直接篡改结果 ajax.then(function() { // 完成 }, function() { // 失败 }) .then(function() { // 完成2 }) console.log(ajax) // 返回deferred对象
-
其他Deferred的promise
function waitHandle() { var dtd = $.Deferred() var wait = function(dtd) { var task = function() { // success dtd.resolve() //error // dtd.reject() } // 异步操作 setTimeout(task, 2000) // 返回Promise,而不是deferred对象 return dtd.Promise() } return wait(dtd) } // 使用 var w = waitHandle() // w接受的是promise对象 // w.reject() 直接会报错 $.when(w) .then(res => { // 完成1 return res }, (err) => { // 错误1 }) .then(res => { // 完成2 return res })
-
总结
-
deferred对象:结果可以直接被篡改(resolve, reject, done,then,fail)
-
promise对象:不可被篡改(resolve, reject,then)
-
promise
-
代码演示
const loadImg = (src) => { return new Promise((resolve, reject) => { const img = document.createElement('img'); img.onload = () => { resolve(img); } img.onerror = () => { reject('加载失败'); } img.src = src; }) } // 异常捕获 loadImg('xxxx').then(res => { // 成功1 }) .then(res => { // 成功2 }) .catch(err => { // 统一捕获异常,代码报错,reject返回错误都能捕获 })
-
Promise.all
// 异步任务全部执行完,才能then const result1 = loadImg('xxxx'); const result2 = loadImg('yyyy'); Promise.all([result1, result2]).then(datas => { // datas是数组 console.log(datas[0]) })
-
Promise.race
// 只要有一个成功,就执行then // result1, result2都是peomise对象 Promise.race([result1, result2]).then(data => { // 最先完成promise的返回值 console.log(data) })
-
Promise标准(ES6)
- 三种状态:pending,fulfilled,rejected
- 状态不可逆:pending -> fulfilled(成功),pending-> rejected(失败)
async-await
-
async/await标准(ES7,需要babel-polyfill)
- await必须包裹在 async 函数里面
- await 后面可以追加promise对象, 获取resolve的值
- await 执行返回的也是一个promise对象
- try-catch可以捕获 promise 中reject的值
-
代码演示
import 'babel-polyfill'; // ES7转ES5 const load = async function () { try { // 异步变成同步写法,依次往下 const result1 = await loadImg('xxx') console.log(result1) const result2 = await loadImg('yyy') console.log(result2) } catch (error) { console.log(error) } } load()
异步解决方案比较
-
callback
-
jquery的deferred
-
generator
-
Promise
-
async/await
网友评论