回調函數(callback) [回調地獄問題,無限回調,維護空難]vue
事件監聽(Listener)node
觀察者模式(發佈訂閱模式) DOM二級綁定多個事件(addEventListener) 原理就是觀察者模式 ,事件池概念出來,jQ多個onios
Promise類面試
Generator函數ajax
Async 函數 (ES2017) 配合Proise使用 [暴爽]axios
eg1:數組
// ==>> callback
function fn(callback) {
var x = 1;
callback && callback(x); //函數fn裏面的變量傳給了他的回調裏面
}
fn(function (val) {
console.log(val);
});
複製代碼
eg2:promise
// ==>> ajax callback
function fn(callback) {
$.ajax({
url: '...',
type: 'get',
success(data) {
if (data.result.code === 200) {
callback && callback(data.result);
}
}
});
}
fn(function (data) {
console.log(data);
});
複製代碼
eg3:bash
// ==>> 回調地獄
function getData() {
//1. 獲取token
$.ajax({
url: '...',
success: function (data) {
if (data.code === 200) {
//2. 獲取用戶信息
$.ajax({
url: '...',
success: function () {
if (data.code === 200) {
//3.獲取用戶相關的新聞
$.ajax({
url: '...',
success: function () {
if (data.code === 200) {
...
}
}
});
}
}
});
}
}
});
}
getData();
複製代碼
行內綁定click異步
給DOM對象綁定方法,方法相同就會有後面覆蓋前面的問題 div1.onclick = function() {};
DOM2二級事件 (addEventListener(eventName,fn, true/false)/attachEvent)
待續...
pendding 進行中
fulfilled 已成功 ==> resolve
rejected 已失敗 ==> reject
pending ==> fulfilled
pending ==> rejected
***一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果, 返回promise實例,鏈式調用
*** Promise的構造函數中代碼是同步執行的,可是then方法是異步執行的,then方法須要等到等到resolve函數執行時才獲得執
*** then返回一個基本或則引用數據類型會自動調用Promise.resolve(val);進行轉爲promise對象,給到下一個then,若是你拋出一個錯誤,這下一個catch會捕獲到
let promsie1 = new Promise((resolve, reject) => {
resolve; 成功
reject;失敗
});
promise instanceof Promise; // ==> true;
promise instanceof Object; // ==> true;
// ==>查看類的屬性和方法(原型上,靜態方法,私有屬性)
console.dir(Promise.prototype);
console.dir(Promise);
console.dir(promise1);
//==>返回Promise實例, then裏面能夠寫兩個函數,表明resolve, reject,可是咱們通常捕獲錯誤,不那麼寫,用catch
promise1.then(data => {
console.log(data);
}).catch(err => {
console.log(err);
});
複製代碼
let promise1 = Promise.resolve(100);
promise1.then(data => {
console.log(data); //==> 100;
});
等價於下面的
let promsie1 = new Promise(resolve =>{
resolve(100);
});
promise1.then(data => {
console.log(data); //==> 100;
});
複製代碼
let x = 2;
let p1 = new Promise((resolve, reject) => {
if (x >=1) {
resolve(x);
} else {
reject('error')
}
});
p1.then(res => {
// return res; // ====>> 返回一個新的Promise實例,進行鏈式調用
return Promise.resolve(res);
}).then(res => {
console.log(res);
}).then(res => {
console.log(111);
});
複製代碼
let promise1 = Promise.reject(100);
promise1.then(data => {
console.log(data); //==> 100;
});
等價於下面的
let promsie1 = new Promise((resolve, reject) =>{
reject(100);
});
promise1.then(data => {
console.log(data);
}).catch(err => {
console.log(data); //==> 100;
});
複製代碼
場景: 當首頁的數據都請求完畢再進行展現出來,就用到了
eg1:
let p1 = Promise.resolve(100);
let p2 = Promise.resolve(200);
let promise2 = Promise.all([p1, p2]);
promise2.then(data => {
let [result1, result2] = data;
console.log(result1, result2); // ==> 100, 200
}).catch(err => {
console.log(err);
});
eg2:
let p1 = Promise.resolve(100);
let p2 = Promise.reject(200);
let promise2 = Promise.all([p1, p2]);
promise2.then(data => {
let [result1, result2] = data; // ==> 數組解構賦值
console.log(result1, result2); // ==> 100, 200
}).catch(err => {
console.log(err);
});
複製代碼
場景: 先來先得
let p1 = Promise.reject('1');
let p2 = Promise.reject('2');
let p3 = Promise.resolve('3');
let p = Promise.race([p1, p2, p3]).then(res => {
console.log(res);
}).catch(err => {
console.log(err); //==> 1
});
複製代碼
let getToken = function() {
...
};
let getUserInfo = function() {
...
};
let p1 = new Promise((resolve, reject) => {
getToken();
});
p1 instanceof Promise; // ==> true
eg2 ================>> : 回家繼續深刻
let p1 = new Promise((resolve, reject) => {
resolve('success...');
}).then(data => {
console.log(data);
return 100; // => return Promise.resolve(100); 沒有return均可以嗎?
}).then(data => {
console.log(data);
return 200; // // => return Promise.resolve(200);
}).then(data => {
console.log(data);
});
success, 100, 200
複製代碼
複製代碼
eg1: Promise的構造函數中代碼是同步執行的,可是then方法是異步執行的,then方法須要等到等到resolve函數執行時才獲得執行。
baijiahao.baidu.com/s?id=158428…
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
// ==> 1 2 4 3
複製代碼
eg2: Promise一旦執行了resolve函數後,就不會再執行reject和其餘的resolve函數了。一旦Promise執行了reject函數,將會被catch函數捕獲,執行catch中的代碼。
const promise = new Promise((resolve, reject) => {
resolve('success1');
reject('error1');
resolve('success2');
reject('error2');
});
promise.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
//==> successs1
複製代碼
eg3: 題目中Promise首先resolve(1),接着就會執行then函數,所以會輸出1,而後在函數中返回2。
注意: return 返回基本數據類型,其實就是 Promise.resolve(value), 若是是返回引用數據類型會沖掉,返回這個對象
const p1 = Promise.resolve(1).then(res=> {
console.log(res);
return 2; // ==>> return Promise.resolve(2);
return Promise.resolve({
a: 1,
b: 2
});
return Promise.reject('error');
}).catch(err => {
console.log(err);
}).then(res=> {
console.log(res);
}).catch(err => {
console.log(err);
});
p1 instanceof Promise; // ==> true
複製代碼
eg4: 經典 setTime/promise (blog.csdn.net/baidu_33295…)
//==> 定時器是隊列
setTimeout(function(){
console.log(1);
}, 0)
// ==>>執行
new Promise(function executor(resolve){
console.log(2);
for(var i = 0; i < 1000; i++){
i = 9999 && resolve(); // ==>> 放到主線程後面
}
console.log(3);
}).then(function(){
console.log(4);
})
console.log(5);
2 3 5 4 1
詳解:
以前說過,在定時器,事件,ajax等操做的時候,會使一個異步操做,會把該操做放到一個task queue裏,須要等當前主線程的任務完成後,會讀取任務隊列(task queue)中的是事件。
那麼,setTimeout會放到任務隊列中,代碼繼續往下走。
因此先輸出2 3。
promise中的then操做是放在<<執行棧>>,也就是主線程的最後。
那麼主線程會繼續往下走咯。
因此輸出 5 4
最後主線程的任務搞完了,纔會去執行task queue中的任務。
因此最後執行1
setTimeout(() => {
console.log(1)
}, 0);
let promse1 = new Promise((resolve, rject) => {
console.log(2);
resolve('ok');
console.log(3);
});
promse1.then(res => {
console.log(4);
}).catch(err => {
console.log(err);
});
console.log(5);
複製代碼
1.語法:
function *show{
yield
}
function* show {
yield
}
複製代碼
2.用法: 配合next關鍵字使用,返回yiled後面的值
function * fn() {
yield 1;
yield 2;
yield 3;
return 'ok';
}
let f = fn();
console.log(f);
Object.prototype.toString.call(f); //==> "[object Generator]"
f.next(); // ==> {value: 1, done:false}
f.next(); // ==> {value: 2, done:false}
f.next(); // ==> {value: 3, done:false}
f.next(); // ==> {value: 'ok', done:true}
f.next(); // ==> {value: undefined, done:true} 完成了
可使用f.next.value; // ==> 拿出來想要的值
複製代碼
3.自動輸出 迭代器 for - of
for (let key of f) {
console.log(key); // ==> 1, 2, 3
}
複製代碼
4.Generator配合解構賦值使用
let [a, b, c, d] = fn();
console.log(a, b, c, d); // ==> 1, 2, 3, undefined 將yield後面的值放到一個數組裏面了
複製代碼
5.Generator配合拓展運算符使用
let [a, ...b] = fn();
console.log(a, b); // ==> 1, [2, 3] 將yield後面的值放到一個數組裏面了
console.log(...fn(); // ==> 1, 2, 3
複製代碼
6.Generator配合Array.from轉爲數組
let f = Array.from(fn()); //==> [1, 2, 3]
console.log([...fn()]);
複製代碼
7.Generator配合axios請求數據
function * fn() {
let val = yield '3653223131';
yield axios.get(`http//sfddd/${token}`);
}
let f = fn(); // ==>>出來一個Generator實例
let userName = f.next().value; // ==>>拿到第一個yield的的值
f.next(userName).value.then(res => { // ==>>將第一個的值傳遞給URL裏面的token, axios返回promise對象
console.log(res);
});
複製代碼
1.語法:
async function fn() { // ==>表示異步,這個函數裏面有異步任務 let result = await xxx //==>表示後面結果須要等待 }
2.特色:
await 只能放到async函數中 (yield只能用在Generator函數中) 可是不是必須的
相比Generator更加語義化
await 後面能夠是promise對象,也能夠是number,string, boolean,自動轉爲promise對象
async函數執行完畢返回promsie對象 默認不寫return的話, 因此還能夠繼續then執行下一步操做
只要await語句後面的Promise狀態變爲reject,那麼整個async函數就會中斷執行 (優化使用try-catch)
async函數能夠沒有await指令和return,都沒有返回promise對象, 有return沒有await返回Promise.resolve(val);
async拋出錯誤,如何解決 ? 只有promise就要進行catch
async函數徹底能夠看做多個異步操做,包裝成的一個 Promise對象,而await命令就是內部then命令的語法糖。resolve成了,數據返回到then裏面,在傳給前面定義的變量
await命令後面是一個 Promise 對象。若是不是,會被轉成一個當即resolve的 Promise 對象。 Promies.resolve();
eg1: 返回promise對象,沒有await狀況
async function fn() {
return 'async'; // ==> return Promise.resolve('async');
}
var f = fn();
f instanceof Promise; // ==> true
f.then(res =>{
console.log(res); // ==> Promise{<resolved>: undefined}****
}).catch(err =>{
console.log(err);
});
複製代碼
eg2:沒有return和await的狀況,
async function fn() {
}
var f = fn();
console.log(f instanceof Promise); // ==> true
f.then(res =>{
console.log(res); // ==> Promise{<resolved>: undefined}
}).catch(err =>{
console.log(err);
});
複製代碼
eg3: 有一個reject值不執行了,中止了
async function fn() {
await Promise.reject('fail');
// ==>>下面代碼都不執行了
await Promise.resolve('success');
console.log(1)
}
var f = fn();
f.then(res => {
console.log(res);
}).catch(err => {
console.log(err); // ==> fail
});
1.try - catch進行捕獲
async function fn() {
try() {
await Promise.reject('fail');
} catch(e){
}
// ==>>下面代碼都不執行了
await Promise.resolve('success');
console.log(1)
}
var f = fn();
f.then(res => {
console.log(res);
}).catch(err => {
console.log(err); // ==> fail
});
2.Promise的catch進行捕獲
async function fn() {
await Promise.reject('fail');
// ==>>下面代碼都不執行了
await Promise.resolve('success');
console.log(1)
}
var f = fn();
f.then(res => {
console.log(res);
}).catch(err => {
console.log(err); // ==> fail
});
複製代碼
eg4: 讀取多個ajax,沒有關係的狀況下
const fs = require('fs');
// ==> 封裝讀取文件函數
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}
async function fn() {
// ==> 三個執都resolve了,纔去對應的執行賦值, 配合解構賦值
let [a, b, c] = await Promise.all([
'./a.txt',
'./b.txt',
'./c.txt'
]);
console.log(a.toString());
console.log(b.toString());
console.log(c.toString());
}
fn();
複製代碼
===> 分別有三個文本文件 a.txt、 b.txt、 c.txt進行讀取裏面的內功,而且依次輸出
1.callback進行讀取
const fs = require('fs'); //==> 導入fs模塊
function fn1(callback) {
fs.readFile('./a.txt', (err, data) => {
if (err) {
console.log(err);
return;
} else {
console.log(data.toString());
callback && callback(() => {
fs.readFile('./c.txt', (err, data) => {
if (err) {
console.log(err);
return;
} else {
console.log(data.toString());
}
})
});
}
});
}
fn1((callback) => {
fs.readFile('./b.txt', (err, data) => {
if (err) {
console.log(err);
return;
} else {
console.log(data.toString());
callback && callback();
}
});
});
複製代碼
// 2.promise讀取文件
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}
readFile('./a.txt').then(res => {
console.log(res.toString());
return readFile('./b.txt');
}).catch(err => {
console.log(err);
}).then(res => {
console.log(res.toString());
return readFile('./c.txt');
}).catch(err => {
console.log(err);
}).then(res => {
console.log(res.toString());
}).catch(err => {
console.log(err);
});
複製代碼
3.Generator讀取文件
const fs = require('fs');
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}
function *gen() {
yield readFile('./a.txt');
yield readFile('./b.txt');
yield readFile('./c.txt');
}
let f = gen(); //==>>先執行Generator返回迭代器
//==> console.log(s = f.next().value); Promise對象 狀態是pending
var s = f.next().value.then(res => { // f.next去執行 readFile('./a.txt'); 返回一個Promise實例進行then和catch
console.log(res.toString());
return f.next().value;
}).catch(err =>{
console.log(err);
}).then(res =>{
console.log(res.toString());
return f.next().value;
}).catch(err =>{
console.log(res);
}).then(res =>{
console.log(res.toString());
}).catch(err =>{
console.log(res);
});
複製代碼
4.async函數讀取文件
const fs = require('fs');
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}
async function gen() {
// ==> 捕獲異常,代碼更加健壯
try {
let file1 = await readFile('./a.txt');
console.log(file1.toString());
let file2 = await readFile('./b.txt');
console.log(file2.toString());
let file3 = await readFile('./c.txt');
console.log(file3.toString());
} catch(e) {
}
}
var s = gen();
console.log(s); // ==> promise對象
複製代碼
5.Promise.all方法去讀取,三個都成功了 resolve,狀態才進行返回,一個失敗了直接catch (這是沒有關係哦!!!三個文件順序的狀況下)
const fs = require('fs');
function readFile(file) {
return new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
});
}
Promise.all([readFile('./a.txt'), readFile('./b.txt'), readFile('./c.txt')]).then(res =>{
let [f1, f2, f3] = res;
console.log(f1.toString(), f2.toString(), f3.toString());
}).catch(err => {
console.log(err);
});
複製代碼
讀取文件:
const fs = require('fs');
class File {
static readFile(fileName) {
if (fileName && fileName.length) {
let promise = new Promise((resolve, reject) => {
fs.readFile(fileName, 'utf-8', (err, data) => {
if (err) {
console.log(err);
}
resolve(data);
});
});
return promise;
}
}
}
// 1. Promies讀取文件
Promise.all([
File.readFile('./b'),
File.readFile('./test')
]).then(res => {
let [a, b] = res;
console.log(a);
console.log(b);
});
//2. async配合Promise讀取文件
const asyncReadFile = async function() {
// 2.1分開寫
let a = await File.readFile('./b');
console.log(a);
let b = await File.readFile('./test');
console.log(b);
// 2.2 Promise.all()寫到一塊
let [x, y] = await Promise.all([File.readFile('./b'), File.readFile('./test')]);
console.log(x);
console.log(y);
return 10;
};
let s = asyncReadFile();
console.log(s);
複製代碼