回调函数
回调函数是什么
自己定义的,没有调用,最终执行了。
同步的回调函数
理解:立即在主线程上执行,不会放入回调队列中
举例: 数组遍历相关的回调函数Promise 的 executor 函数
异步的回调函数
理解:不会立即执行,会放入回调队列以后执行。
举例:定时器的回调,Promise的成功/失败的结果/ajax的回调
代码浏览器报错
| Error | 所有错误的父类型 |
|---|---|
| ReferenceError | 引用的变量不存在 |
| TypeError | 数据类型不正确 |
| SyntaxError | 语法错误 |
Promise 理解笔记
Promise是js中解决异步编程的新方案(旧的方案为,纯粹的回调函数) (Promise本身是同步的)
Promise是一个状态机,它可以被分为三种状态:pending(进行中)、fulfilled(已完成)、rejected(已失败)
// 具体的表达
//从语法上说: Promise是一个内置的构造函数
//从功能上说: Promise的实例对象可以用来封装一个一部操作,并可以获取成功/失败的值。
理解
// 1.Promise 不是回调,是一个内置的构造函数,在new 的时候调用
// 2.Promise的构造函数接受一个函数作为参数,(要传入一个回调函数),并且是一个同步函数;MDN将此函数称之为executor函数。它是同步的回调,会立即在主线程上执行
// 3.每一个Promise实例在刚被new出来的那一刻,状态都是初始化状态,即pending。
// 4.executor函数有俩个参数,resolve,reject,都是函数,用来处理Promise的状态变化。
// (1)调用resolve,会让Promise的状态变为fulfilled,同时可以指定成功的value值。
// (2)调用reject,会让Promise的状态变为rejected,同时可以指定失败的reason(原因)值。
let p = new Promise((resolve, reject) => {
// console.log(resolve, reject);
// console.log(reject('hello,该参数是失败的值'));
resolve('hello,该参数是成功的值','45');
}).then((resolve)=>{
console.log(resolve);
}).catch((reject)=>{
console.log(reject);
})
状态值的改变
// Promise的实例状态有三种:pending、fulfilled、rejected
// (1)执行resolve(value)方法,改变状态为fulfilled,并且设置结果值
// (2)执行reject(reason)方法,改变状态为rejected,并且设置结果值
// (3)执行器函数,抛出异常:如果当前是pending状态,则改变状态为rejected,并且设置结果值
// 需要注意的是: Promise 的状态只能改变一次
Promise.all与Promise.race
// Promise.all() 方法有一个参数,这个参数是一个数组,数组里面的每一项都是一个 Promise 对象。
// 一个失败,就返回失败的结果
// 当数组里面的每一项都执行完成后,Promise.all() 方法会返回一个新的 Promise 对象,这个新的 Promise 对象会在数组里面的每一项都执行完成后才执行。
let p1 = Promise.resolve(1);
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
}, 1000);
});
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3);
}, 2000);
});
let p4 = Promise.all([p1, p2, p3])
p4.then(data => {
console.log(data)
}).catch(
err => {
console.log(err);
}
)
// Promise.race() 类似一个赛道的形式;那个promise先执行完成就输出那个结果;不论成功还是失败
链式调用(用来解决回调地狱的问题)
// Promise 实例 .then() 返回的是一个新的Promise实例,这个新的Promise实例会根据状态来执行下一步的操作。
// 1:如果then所指定的回调返回的是非Promise值
// 那么--新的Promise实例的状态为:成功(fulfilled),成功的value为a
// 2:如果then所指定的回调返回的是一个Promise实例
// 那么--新的Promise实例的状态,值,都与p一致
// 3:如果then所指定的回调抛出异常:
// 那么--新的Promise实例的状态为:失败(rejected),失败的reason为抛出的那个异常
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('success');
}, 1000);
})
p1.then(
value => {
console.log('成功1', value); return Promise.reject('a')
}, reason => {
console.log('失败1', reason);
}
).then(
value => {
console.log('成功2', value); return true
}, reason => {
console.log('失败2', reason); return 100
}
).then(
value => {
console.log('成功3', value); return false
}, reason => {
console.log('失败3', reason); return false
}
).then(
value => {
console.log('成功4', value); return -100
}, reason => {
console.log('失败4', reason); return false
}
);
// 输出
// 失败1 success
// 60 成功2 undefined
// 66 成功3 true
// 72 成功4 false
async与await(解决回调地狱的终极方案)
async 与 await 是es7提出的解决异步的方案
await必须在async修饰的函数中使用(可以获取到成功的结果)
如果想要获取失败的原因,需要通过try {
} catch (error) {
} 来捕获处理。
并且await 必须搭配async 使用不能单独使用
一个async可以搭配多个await使用反之不可
宏任务与微任务
// 宏任务与微任务
// 事件,ajax,定时器是一个宏任务/宏队列
// 每一个宏任务在执行的同时,必须要保证微任务当中没有任务了
// Promise是一个微任务/维队列
// 目前经常用到的只有一个promise实例,属于微任务
// 微任务优先级高于宏任务
setTimeout(() => {
console.log('setTimeout1');
});
setTimeout(() => {
console.log('setTimeout2');
});
Promise.resolve().then(() => {
console.log('Promise.resolve1');
});
Promise.resolve().then(() => {
console.log('Promise.resolve2');
});
//输出:setTimeout1,setTimeout2,Promise.resolve1,Promise.resolve2
setTimeout(()=>{
console.log('0'); //宏任务
},0);
new Promise((resolve,reject)=>{ //微任务
console.log('1');
resolve();
}).then(()=>{
console.log('2');
new Promise((resolve, reject) => {
console.log('3');
resolve();
}).then(() => {
console.log('4');
}).then(() => {
console.log('5');
});
}).then(() => {
console.log('6');
});
new Promise((resolve, reject) => {
console.log('7');
resolve();
}).then(() => {
console.log('8');
})
// 输出:1 7 2 3 8 4 6 5 0