第1章 課程介紹
1-1 導(dǎo)學(xué)
課程概述
- 做什么烦绳?— 講解前端 JS 高級面試題
- 哪些部分澄港?— 高級基礎(chǔ), 框架原理, app混合開發(fā)
- 技術(shù)劳景?— JS誉简、ES6、虛擬DOM枢泰、vue描融、React、hybrid
知識(shí)點(diǎn)介紹
- 基礎(chǔ)知識(shí):ES6 常用語法衡蚂、原型高級應(yīng)用窿克、異步全面講解
- 框架原理:虛擬 DOM、MVVM vue毛甲、組件化 React
- 混合開發(fā):hybrid年叮、hybrid vs H5、前端客戶端通訊
課程安排
- 高級基礎(chǔ)
- ES6 常用語法:Class Module Promise 等
- 原型高級應(yīng)用:結(jié)合 jQuery 和 zepto 源碼
- 異步全面講解:從原理到 jQuery 再到 Promise
- 框架原理
- 虛擬 DOM:存在價(jià)值玻募,如何使用只损,diff 算法
- vue:MVVM,vue 響應(yīng)式七咧、模板解析跃惫、渲染
- React:組件化,JSX艾栋,vdom爆存,setState
- 對比:有主見,自圓其說
- App混合開發(fā)
- hybrid:基礎(chǔ)蝗砾、和 h5 對比先较,上線流程
- 通訊:通訊原理,JS-Bridge 封裝
講授方式
- 先出面試題悼粮,帶領(lǐng)大家思考
- 通過題目引出知識(shí)點(diǎn)闲勺,擴(kuò)充講解知識(shí)體系
- 最后通過學(xué)到的知識(shí)點(diǎn),解答題目
課程收獲
- 從深度和廣度都擴(kuò)充了自己的知識(shí)體系
- 學(xué)會(huì)如何高效學(xué)習(xí)
- 深入理解常用框架的實(shí)現(xiàn)原理和 hybrid 應(yīng)用
1-2 課程重要提示
1-3 架構(gòu)-題目
ES6
模塊化的使用和編譯環(huán)境扣猫?
Class 與 JS 構(gòu)造函數(shù)的區(qū)別菜循?
Promise 的用法?
ES6 其他常用功能苞笨?
異步
什么是單線程债朵,和異步有什么關(guān)系子眶?
什么是 event-loop?
目前 JS 解決異步的方案有哪些序芦?
如果只用 jquery 如何解決異步臭杰?
Promise 的標(biāo)準(zhǔn)?
async/await 的使用谚中?
原型
原型如何實(shí)際應(yīng)用渴杆?
原型如何滿足擴(kuò)展?
vdom
什么是 vdom宪塔,為何要用 vdom磁奖?
vdom如何使用,核心函數(shù)有哪些某筐?
了解 diff 算法嗎比搭?
MVVM
之前使用 jquery 和現(xiàn)在使用 Vue 或 React 框架的區(qū)別?
你如何理解MVVM南誊?
Vue 如何實(shí)現(xiàn)響應(yīng)式身诺?
Vue 如何解析模版?
介紹 Vue 的實(shí)現(xiàn)流程抄囚?
組件化
對組件化的理解霉赡?
JSX 是什么?
JSX 和 vdom 什么關(guān)系幔托?
簡述 React 的 setState穴亏?
簡述自己如何比較 React 和 Vue?
hybrid
hybrid 是什么重挑,為何要用hybrid嗓化?
hybrid 如何更新上線?
hybrid 和 h5 有何區(qū)別谬哀?
JS 如何與客戶端通信蟆湖?
第2章 ES6 語法
2-1 開始
ES6
- 開發(fā)環(huán)境已經(jīng)普及使用
- 瀏覽器環(huán)境卻支持不好(需要開發(fā)環(huán)境編譯)
- 內(nèi)容很多,重點(diǎn)了解常用語法
- 面試:開發(fā)環(huán)境的使用 + 重點(diǎn)語法的掌握
題目
- ES6 模塊化如何使用玻粪,開發(fā)環(huán)境如何打包?
- Class 和普通構(gòu)造函數(shù)有何區(qū)別诬垂?
- Promise 的基本使用和原理劲室?
- 總結(jié)一下 ES6 其他常用功能?
2-2 模塊化
【題目】
ES6 模塊化如何使用结窘,開發(fā)環(huán)境如何打包很洋?
【知識(shí)點(diǎn)】
1. 模塊化的基本語法
- export 語法
// util1.js
export default {
a: 100
};
// util2.js
export function fn1() {
alert('fn1');
};
export function fn2() {
alert('fn2');
};
- import 語法
// index.js
import util1 from './util1.js';
import { fn1, fn2 } from './util2.js';
console.log(util1);
fn1();
fn2();
2. 開發(fā)環(huán)境配置
babel
- 安裝 babel
1. 電腦有 node 環(huán)境,運(yùn)行 npm init
2. npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest
3. 創(chuàng)建 .babelrc 文件隧枫,輸入以下內(nèi)容:
{
"presets": ["es2015", "latest"],
"plugins": []
}
4. sudo npm install -g babel-cli
5. babel --version
- 使用 babel
1. 創(chuàng)建:./src/index.js
2. 內(nèi)容:[1, 2, 3].map(item => item + 1);
3. 運(yùn)行:babel ./src/index.js
webpack
- 安裝 webpack
此處 babel-loader 需要指定版本喉磁,不然掉坑
https://www.cnblogs.com/jiebba/p/9618930.html - 使用 webpack
1. npm install webpack webpack-cli babel-loader@^7.1.2 --save-dev
2. 配置 webpack.config.js谓苟,輸入以下內(nèi)容:
module.exports = {
entry: './src/index.js',
output: {
path: __dirname,
filename: './build/bundle.js'
},
module: {
rules: [{
test: /\.js?$/,
exclude: /{node_modules}/,
loader: 'babel-loader'
}]
}
}
3. 配置 package.json 中的 scripts
"scripts": {
"start": "webpack"
}
4. 運(yùn)行 npm start
5. 創(chuàng)建:index.html
<script type="text/javascript" src="./build/bundle.js"></script>
6. http-server -p 8881
7. 訪問 http://localhost:8881/index.html
rollup
- 安裝 rollup
https://www.rollupjs.com/guide/tutorial rollup 中文網(wǎng)
1. npm init
2. npm i rollup rollup-plugin-node-resolve rollup-plugin-babel@^3.0.3 babel-plugin-external-helpers babel-preset-latest babel-core --save-dev
3. 配置 .babelrc
{
"presets": [
["latest", {
"es2015": {
"modules": false
}
}]
],
"plugins": ["external-helpers"]
}
4. 配置 rollup.config.js
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'src/index.js',
output: {
file: 'build/bundle.js',
format: 'cjs'
},
plugins: [
resolve(),
babel({
exclude: 'node_modules/**'
})
]
};
- 使用 rollup
1. 將 webpack 環(huán)境的 JS 代碼拷貝過來
2. 修改 package.json 的 scripts
"scripts": {
"start": "rollup -c rollup.config.js"
}
3. 運(yùn)行 npm start
- 關(guān)于工具
rollup 功能單一,webpack 功能強(qiáng)大
參考設(shè)計(jì)原則和《Linux/Unix設(shè)計(jì)思想》
工具要盡量功能單一协怒,可集成涝焙,可擴(kuò)展
wangEditor 用的 gulp + rollup
3. 關(guān)于 JS 眾多模塊化標(biāo)準(zhǔn)
- 沒有模塊化
- AMD 成為標(biāo)準(zhǔn),require.js (也有 CMD)
- 前端打包工具孕暇,是的 nodejs 模塊化可以被使用
- ES6 出現(xiàn)仑撞,想統(tǒng)一現(xiàn)在所有模塊化標(biāo)準(zhǔn)
- nodejs 積極支持,瀏覽器尚未統(tǒng)一
- 你可以自造 lib 妖滔,但是不要自造標(biāo)準(zhǔn)K硐!座舍!
【解答】
- 語法: import export (注意有無 default)
- 環(huán)境: babel 編譯 ES6 語法沮翔,模塊化可用 webpack 和 rollup
- 擴(kuò)展: 說一下自己對模塊化標(biāo)準(zhǔn)統(tǒng)一的期待
2-9 class
【題目】
Class 與 JS 構(gòu)造函數(shù)的區(qū)別?
- Class 在語法上更加貼合面向?qū)ο蟮膶懛?/li>
- Class 實(shí)現(xiàn)繼承更加易讀曲秉、易理解
- 更易于寫 java 等后端語言的使用
- 本質(zhì)還是語法糖采蚀,使用 prototype
【知識(shí)點(diǎn)】
JS 構(gòu)造函數(shù)
function MathHandle(x, y) {
this.x = x;
this.y = y;
}
MathHandle.prototype.add = function () {
return this.x + this.y;
};
var m = new MathHandle(1, 2);
console.log(m.add());
// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true
Class 基本語法
class MathHandle {
constructor (x, y) {
this.x = x;
this.y = y;
}
add() {
return this.x + this.y;
}
}
const m = new MathHandle(1, 2);
console.log(m.add());
// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true
語法糖
class MathHandle {
// ...
}
typeof MathHandle // "function"
MathHandle === MathHandle.prototype.constructor // true
繼承
- 繼承 - JS
ES6 之前的繼承,是把低級構(gòu)造函數(shù)的原型岸浑,賦值成高級構(gòu)造函數(shù)的實(shí)例這種方式來實(shí)現(xiàn)的
// 動(dòng)物
function Animal() {
this.eat = function () {
console.log('animal eat');
}
}
// 狗
function Dog() {
this.bark = function () {
console.log('dog bark');
}
}
// 綁定原型搏存,實(shí)現(xiàn)繼承
Dog.prototype = new Animal();
// 哈士奇
var hashiqi = new Dog();
hashiqi.eat(); // animal eat
hashiqi.bark(); // dog bark
- 繼承 - Class
// 動(dòng)物
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} eat`);
}
}
// 狗
class Dog extends Animal {
constructor(name) {
super(name);
this.name = name;
}
say() {
console.log(`${this.name} say`);
}
}
// 哈士奇
const dog = new Dog('哈士奇');
dog.say(); // 哈士奇 say
dog.eat(); // 哈士奇 eat
【解答】
class Ad extends Component {
constructor(props) {
super(props);
this.state = {
data: []
}
}
render() {
return (
<div>Hello, World!</div>
)
}
componentDidMount() {
}
}
2-13 Promise
【題目】
Promise 的用法?
【知識(shí)點(diǎn)】
Promise 的基本使用
- Callback Hell
function loadImg(src, callback, fail) {
var img = document.createElement('img');
img.onload = function () {
callback(img);
}
img.onerror = function () {
fail();
}
img.src = src;
}
var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
loadImg(src, function (img) {
console.log(img.width);
}, function () {
console.log('failed');
})
- Promise 語法
function loadImg(src) {
const promise = new Promise(function (resolve, reject) {
var img = document.createElement('img');
img.onload = function () {
resolve(img);
}
img.onerror = function () {
reject();
}
img.src = src;
})
return promise;
};
var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);
result.then(function (img) {
console.log(img.width);
}, function () {
console.log('failed');
});
result.then(function (img) {
console.log(img.height);
});
【解答】
- new Promise 實(shí)例矢洲,而且要 return
- new Promise 時(shí)要傳入函數(shù)璧眠,函數(shù)有 resolve reject 兩個(gè)參數(shù)
- 成功時(shí)執(zhí)行 resolve() 失敗時(shí)執(zhí)行 reject()
- then 監(jiān)聽結(jié)果
2-16 總結(jié)一下 ES6 其他常用功能
題目
總結(jié)一下 ES6 其他常用功能?
- let/const
- 多行字符串/模板變量
- 解構(gòu)賦值
- 塊級作用域
- 函數(shù)默認(rèn)參數(shù)
- 箭頭函數(shù) (this)
知識(shí)點(diǎn)
- let/const
// JS
var i = 10;
i = 100;
// ES6
let i = 10;
i = 100; // 正確
const j = 20;
j = 200; // 報(bào)錯(cuò)
- 多行字符串/模板變量
// JS
var name = 'zhangsan', age = 20, html = '';
html += '<div>';
html += ' <p>' + name + '</p>';
html += ' <p>' + age + '</p>';
html += '</div>';
// ES6
const name = 'zhangsan', age = 20;
const html = `<div>
<p>${name}</p>
<p>${age}</p>
</div>`;
console.log(html);
- 解構(gòu)賦值
// JS
var obj = { a: 100, b: 200 };
var a = obj.a;
var b = obj.b;
var arr = ['xxx', 'yyy', 'zzz'];
var x = arr[0];
// ES6
const obj = { a: 10, b: 20, c: 30 };
const { a, c } = obj;
console.log(a);
console.log(c);
const arr = ['xxx', 'yyy', 'zzz'];
const [x, y, z] = arr;
console.log(x);
console.log(y);
console.log(z);
- 塊級作用域
// JS
var obj = { a: 100, b: 200 };
for (var item in obj) {
console.log(item);
}
console.log(item); // 'b'
// ES6
const obj = { a: 100, b: 200 };
for (let item in obj) {
console.log(item);
}
console.log(item); // undefined
- 函數(shù)默認(rèn)參數(shù)
// JS
function fn(a, b) {
if (b == null) {
b = 0;
}
}
// ES6
function fn(a, b=0) {
}
- 箭頭函數(shù)
// JS
var arr = [1, 2, 3];
arr.map(function (item) {
return item + 1;
});
// ES6
const arr = [1, 2, 3];
arr.map(item => item + 1);
arr.map((item, index) => {
console.log(index);
return item + 1;
});
function fn() {
console.log('real', this); // {a: 100}
var arr = [1, 2, 3];
// 普通 JS
arr.map(function (item) {
console.log('js', this); // window
return item + 1;
});
// 箭頭函數(shù)
arr.map(item => {
console.log('es6', this); // {a: 100}
return item + 1;
});
}
fn.call({a: 100});
第3章 原型
3-1 開始
- 《前端 JS 面試技巧》已經(jīng)講解過原型的基礎(chǔ)知識(shí)
- 高級面試題读虏,光會(huì)原型基礎(chǔ)還不夠责静,還要實(shí)際應(yīng)用
- zepto jquery 中如何用原型?
- 順便也算是解讀了 zepto 和 jquery 的部分源碼
題目
原型如何實(shí)際應(yīng)用盖桥?
- jquery 和 zepto 的簡單使用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>jquery test 1</p>
<p>jquery test 2</p>
<p>jquery test 3</p>
<div id="div1">
<p>jquery test in div</p>
</div>
<script type="text/javascript" src="./jquery-3.2.1.js"></script>
<script type="text/javascript">
var $p = $('p');
$p.css('color', 'red'); // css 是原型方法
console.log($p.html()); // html 是原型方法
var $div1 = $('#div1')
$div1.css('color', 'blue'); // css 是原型方法
console.log($div1.html()); // html 是原型方法
</script>
</body>
</html>
- zepto 如何使用原型
(function (window) {
var zepto = {};
function Z(dom, selector) {
var i, len = dom ? dom.length : 0;
for (i = 0; i < len; i++) {
this[i] = dom[i];
}
this.length = len;
this.selector = selector || '';
}
zepto.Z = function (dom, selector) {
return new Z(dom, selector);
};
zepto.init = function (selector) {
var slice = Array.prototype.slice;
var dom = slice.call(document.querySelectorAll(selector));
return zepto.Z(dom, selector);
};
var $ = function (selector) {
return zepto.init(selector);
};
window.$ = $
$.fn = {
css: function (key, value) {
alert('css');
},
html: function (value) {
return '這是一個(gè)模擬的 html 函數(shù)';
}
}
Z.prototype = $.fn;
})(window);
- jquery 如何使用原型
(function (window) {
var jQuery = function (selector) {
return new jQuery.fn.init(selector)
};
jQuery.fn = {
css: function (key, value) {
alert('css');
},
html: function (value) {
return 'html';
}
};
var init = jQuery.fn.init = function (selector) {
var slice = Array.prototype.slice;
var dom = slice.call(document.querySelectorAll(selector));
var i, len = dom ? dom.length : 0;
for (i = 0; i < len; i++) {
this[i] = dom[i];
}
this.length = len;
this.selector = selector || '';
}
init.prototype = jQuery.fn;
window.$ = jQuery;
})(window);
原型如何滿足擴(kuò)展灾螃?
第4章 異步
- 《前端 JS 面試技巧》講到異步的基礎(chǔ)
- 高級面試會(huì)問到更多的內(nèi)容
- 如 event-loop Promise Async/Await 等
題目
什么是單線程,和異步有什么關(guān)系揩徊?
- 單線程 - 只有一個(gè)線程腰鬼,同一時(shí)間只能做一件事
// 循環(huán)運(yùn)行期間,JS 執(zhí)行和 DOM 渲染暫時(shí)卡頓
var i, sum = 0;
for (i = 0; i < 1000000000; i++) {
sum += i;
}
console.log(sum);
// alert 不處理塑荒, JS 執(zhí)行和 DOM 渲染暫時(shí)卡頓
console.log(1);
alert('hello');
console.log(2);
- 原因 - 避免 DOM 渲染的沖突
瀏覽器需要渲染 DOM
JS 可以修改 DOM 結(jié)構(gòu)
JS 執(zhí)行的時(shí)候熄赡,瀏覽器 DOM 渲染會(huì)暫停
兩段 JS 也不能同時(shí)執(zhí)行(都修改 DOM 就沖突了)
webworker 支持多線程,但是不能訪問 DOM
- 解決方案 - 異步
什么是 callback齿税?異步完成之后要執(zhí)行的函數(shù)
問題一:沒按照書寫方式執(zhí)行彼硫,可讀性查
問題二:callback 中不容易模塊化
什么是 event-loop?
- 文字解釋
事件輪詢,JS 實(shí)現(xiàn)異步的具體解決方案
同步代碼拧篮,直接執(zhí)行
異步函數(shù)先放在 "異步隊(duì)列" 中
待同步函數(shù)執(zhí)行完畢词渤,輪詢執(zhí)行 "異步隊(duì)列" 的函數(shù)
如果只用 jquery 如何解決異步?- Deferred
- 是否用過 jQuery 的 Deferred
jQuery 1.5 的變化
使用 jQuery Deferred
初步引入 Promise 概念
- jQuery 1.5 的變化 - 1.5 之前
var ajax = $.ajax({
url: 'data.json',
success: function () {
console.log('success1');
console.log('success1');
console.log('success1');
},
error: function () {
console.log('error');
}
})
console.log(ajax); // 返回一個(gè) XHR 對象
- jQuery 1.5 的變化 - 1.5 之后
var ajax = $.ajax('data.json');
ajax.done(function () {
console.log('success 1');
})
.fail(function () {
console.log('error');
})
.done(function () {
console.log('success 2');
})
console.log(ajax); // 返回一個(gè) deferred 對象
// 很像 Promise 的寫法
var ajax = $.ajax('data.json');
ajax.then(function () {
console.log('success 1');
}, function () {
console.log('error 1');
})
.then(function () {
console.log('success 2');
}, function () {
console.log('error 2');
})
- jQuery 1.5 的變化
無法改變 JS 異步和單線程的本質(zhì)
只能從寫法上杜絕 callback 這種形式
它是一種語法糖形式串绩,但是解耦了代碼
很好的體現(xiàn):開放封閉原則 ( 對擴(kuò)展開發(fā)缺虐,對修改封閉 )
- 使用 jQuery Deferred
var wait = function () {
var task = function () {
console.log('執(zhí)行完成');
console.log('此處新需求......');
console.log('第一步');
console.log('第二步');
console.log('第三步');
};
setTimeout(task, 2000);
};
wait();
function waitHandle() {
var dtd = $.Deferred();
var wait = function (dtd) {
var task = function () {
console.log('執(zhí)行完成');
dtd.resolve();
// dtd.reject()
}
setTimeout(task, 2000);
return dtd.promise(); // return dtd; => return dtd.promise();
}
return wait(dtd);
}
var w = waitHandle();
// w.then(function () {
// => 1.w 接收到的不再是一個(gè) dtd 對象,而是一個(gè) promise 對象
// => 2.只有 .then .done .fail 這種被動(dòng)監(jiān)聽方法
// => 3.不再支持 .resolve .reject 這種主動(dòng)方法的調(diào)用
$.when(w).then(function () {
console.log('ok 1');
}, function () {
console.log('err 1');
});
- jQuery 里引入 promise
總結(jié)赏参,dtd 的 API 可分成兩類志笼,用意不同
第一類: dtd.resolve dtd.reject
第二類: dtd.then dtd.done dtd.fail
這兩類應(yīng)該分開,否則后果很嚴(yán)重把篓!
可以在上面代碼最后執(zhí)行 dtd.reject() 試一下后果
Promise 的基本使用和原理纫溃?
- 基本語法回顧
function loadImg(src) {
const promise = new Promise(function (resolve, reject) {
var img = document.createElement('img');
img.onload = function () {
resolve(img);
}
img.onerror = function () {
reject();
}
img.src = src;
})
return promise;
};
var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);
result.then(function (img) {
console.log(img.width);
}, function () {
console.log('failed');
});
result.then(function (img) {
console.log(img.height);
});
- 異常捕獲
// 捕獲程序錯(cuò)誤異常
// throw new Error('自定義錯(cuò)誤');
result.then(function (img) {
console.log(img.width);
return img;
}).then(function (img) {
console.log(img.height);
}).catch(function (ex) {
// 統(tǒng)一捕獲異常
console.log(ex);
})
// 捕獲業(yè)務(wù)邏輯異常
// reject('圖片加載失敗');
// var src = 'https://cover042_sXXX.jpg';
result.then(function (img) {
console.log(img.width);
return img;
}).then(function (img) {
console.log(img.height);
}).catch(function (ex) {
// 統(tǒng)一捕獲異常
console.log(ex);
})
- 多個(gè)串聯(lián)
//業(yè)務(wù)需求;先加載一個(gè)韧掩,再加載另外一個(gè)
var src1 = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result1 = loadImg(src1);
var src2 = 'https://coding.imooc.com/static/module/class/content/img/190/section5-img.png';
var result2 = loadImg(src2);
// 鏈?zhǔn)讲僮?result1.then(function (img) {
console.log('第一個(gè)圖片加載完成', img.width); // 240
return result2;
}).then(function (img) {
console.log('第二個(gè)圖片加載完成', img.width); // 998
}).catch(function (ex) {
// 統(tǒng)一捕獲異常
console.log(ex);
})
- Promise.all 和 Promise.race
// 全部完成才執(zhí)行
Promise.all([result1, result2]).then(function (datas) {
console.log(datas[0]);
console.log(datas[1]);
});
// 只要有一個(gè)完成就執(zhí)行
Promise.race([result1, result2]).then(function (data) {
console.log(data);
});
- Promise 標(biāo)準(zhǔn)
// 關(guān)于“標(biāo)準(zhǔn)”的閑談
任何技術(shù)推廣使用都需要一套標(biāo)準(zhǔn)來支撐
如 html js css http 等紊浩,無規(guī)矩不成方圓
任何不符合標(biāo)準(zhǔn)的東西,終將會(huì)被用戶拋棄
不要挑戰(zhàn)標(biāo)準(zhǔn)疗锐,不要自造標(biāo)準(zhǔn)
// Promise 標(biāo)準(zhǔn) - 狀態(tài)變化
三種狀態(tài):pending fulfilled rejected
初始狀態(tài)是 pending
pending 變?yōu)?fulfilled 坊谁,或者 pending 變?yōu)?rejected
狀態(tài)變化不可逆
// Promise 標(biāo)準(zhǔn) - then
Promise 實(shí)例必須實(shí)現(xiàn) then 這個(gè)方法
then() 必須可以接收兩個(gè)函數(shù)作為參數(shù)
then() 返回的必須是一個(gè) Promise 實(shí)例
介紹一下 async/await(和 Promise 的區(qū)別、聯(lián)系)滑臊?
- then 只是將 callback 拆分了
var w = waitHandle();
w.then(function () {
console.log('ok 1');
}, function () {
console.log('err 1');
}).then(function () {
console.log('ok 2');
}, function () {
console.log('err 2');
});
- async/await 是最直接的同步寫法
const load = async function () {
const result1 = await loadImg(src1);
console.log(result1);
const result2 = await loadImg(src2);
console.log(result2);
}
load();
- 語法
使用 await 口芍,函數(shù)必須用 async 標(biāo)識(shí)
await 后面跟的是一個(gè) Promise 實(shí)例
需要 babel-polyfill
- 坑來了
// webpack 打包
1.首先,npm i babel-polyfill -D
2.運(yùn)行報(bào)錯(cuò)雇卷,Uncaught ReferenceError: regeneratorRuntime is not defined
3.在 .babelrc 文件中添加:
"plugins": [
[
"transform-runtime",
{
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": "babel-runtime"
}
]
]
4.運(yùn)行報(bào)錯(cuò)鬓椭,ReferenceError: Unknown plugin "transform-runtime" specified
5.npm install babel-plugin-transform-runtime -D
6.運(yùn)行再次報(bào)錯(cuò),Cannot use import statement outside a module
7.<script type="module"></script>
8.成功
// rollup 打包
1.npm i babel-polyfill -D
之前也報(bào)和 webpack 相同的錯(cuò)誤关划,自己就好了小染,原因未知
- 小結(jié)
promise 是對異步回調(diào)的封裝
async await 是使用 promise 時(shí)的一種擴(kuò)展
完全是同步的寫法,再也沒有回調(diào)函數(shù)
但是:改變不了 JS 單線程贮折、異步的本質(zhì)
目前 JS 解決異步的方案有哪些裤翩?
- jQuery Deferred
- Promise
- Async/Await
- Generator