JS異步方案
單線程和event-loop
單線程:JS引擎線程只有一個,避免多線程DOM渲染沖突(GUI渲染線程互斥也是同理)
異步:解決JS單線程只能同時做一件事的問題,
event-loop:主線程從任務隊列中讀取事件,這個過程是循環(huán)不斷的,實現(xiàn)異步的具體解決方案
callback
-
代碼演示:
$.ajax({ url: 'xxx', success: function(res => { }) })
jquery的deferred
概念:jquery1.5版本之后ajax的實現(xiàn)就用的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 => { // 統(tǒng)一捕獲異常,代碼報錯,reject返回錯誤都能捕獲 }) -
Promise.all
// 異步任務全部執(zhí)行完,才能then const result1 = loadImg('xxxx'); const result2 = loadImg('yyyy'); Promise.all([result1, result2]).then(datas => { // datas是數組 console.log(datas[0]) }) -
Promise.race
// 只要有一個成功,就執(zhí)行then // result1, result2都是peomise對象 Promise.race([result1, result2]).then(data => { // 最先完成promise的返回值 console.log(data) }) -
Promise標準(ES6)
- 三種狀態(tài):pending,fulfilled,rejected
- 狀態(tài)不可逆:pending -> fulfilled(成功),pending-> rejected(失?。?/li>
async-await
-
async/await標準(ES7,需要babel-polyfill)
- await必須包裹在 async 函數里面
- await 后面可以追加promise對象, 獲取resolve的值
- await 執(zhí)行返回的也是一個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