这是我参与「第四届青训营 」笔记创作活动的第3天
this的指向问题
- 全局作用域或普通函数中this指向全局变量对象window(定时器里面的this指向window)
- 方法调用中谁调用this指向谁
- 构造函数中this指向构造函数的实例
- 一般情况下this的最终指向是那个调用它的对象
js执行机制
单线程——>解决:异步
同步和异步
异步是指可能比较长时间才有结果的才做,如网络请求(ajax) 读取本地文件 定时器
宏任务和微任务
- 前者:js主线程中的同步代码、定时器、事件绑定 ajax 读取文件
- 后者:promise中的then、async await、generator
- 流程:同步程序->process.nextTick->微任务——>宏任务——>setlmmediate->(后面的事件循环)有延时的计时器
同步任务和异步任务
- 先执行完执行栈中的所有同步任务,再读取任务队列中的异步任务,将其进入执行栈中,开始执行。
- 事件循环:检测是否还有任务
异步又分为:
回调函数
- 导致回调地狱
- js中用到回调函数的地方很多,除了定时器以外还有事件监听,以及后面会学到的ajax等。
promise
- Promise是异步编程得一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve、race这几个方法,原型上有then、catch等方法
- Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
- 调用resolve才会执行then
特点
- 对象的状态不受外界影响
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled和从pending变为rejected。
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)
var p=new Promise(function(resolve(异步操作执行成功后的回调函数),reject(异步操作执行失败后的回调函数)){
//executor执行器函数在传入的时候,它会立即执行
//做一些异步操作
})
console.log(p); //得到一个promise对象
then方法的使用
//实例化
const p = new Promise(function(resolve, reject) {
setTimeout(function() {
//成功
let data = 'su';
resolve(data);
//resolve() 中可以放置一个参数用于向下一个 then 传递一个值
//失败
let err = 'shibai';
reject(err);
}, 1000);
});
//调用promise对象的then方法
//成功
p.then(function(value) {
console.log(value);
//成功的回调回调,回调函数的第一个参数为成功时返回的promise对象
}, function(reason) {
console.error(reason);
//失败的回调函数,回调函数的第一个参数为失败的promise对象
})
let p = new Promise((resolve, reject) => {
resolve('OK');
//reject('Error')
});
p.then(data=>{
console.log(data);//ok
},reason=>{
console.log(reason);//当第返回的结果不是resolve而是上面的reject,则此处打印 error
})
then链式调用
then函数本身为promise构造函数的实例——>then链式调用
- 当resolve执行后,promise状态指定为resolved,执行成功的回调
- 每一次then的执行中参数的data都为上一次异步函数执行的返回值
- 若上一次无返回值,则输出undefined.错误同理
- 在结尾加上catch进行错误捕获,用来中断链条,并且捕获错误原因
catch方法的使用
- 其实它和then的第二个参数一样,用来指定reject的回调
- 在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中,而且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了
- catch方法接受一个回调函数
let p = new Promise((resolve, reject) => {
reject('error');
});
p.catch(reason => {
console.log(reason);
});//error
Promise.resolve,Promise.reject方法的使用
resolve和reject都接收一个参数
如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
reject在任何情况下都返回失败的rejected对象
let p1 = Promise.resolve(521);
//resolve获取到521为非promise对象,返回成功的promise对象,值为传入的值
let p2 = Promise.resolve(new Promise((resolve, reject) => {
//resolve('Success')//Promise {<fulfilled>: 'Success'}
reject('Error');
//当参数为promise对象时,返回的值为内部promise对象执行的结果
}));
console.log(p1);//Promise {<fulfilled>: 521}
console.log(p2);//Promise {<rejected>: 'Error'}
Promise.all方法的使用
- 获取一个promise对象组成的数组,它会等待数组中所有的promise对象执行完毕后返回他们各自返回的结果组成的数组
- all方法返回的是一个数组,与传入数组的长度相同
- then只有当all中数组中所有异步全部得到结果之后,才执行回调,谁跑的慢,以谁为准执行回调
- all接收一个数组参数,里面的值最终都算返回Promise对象
- Promise.all([p1, p2, p3]).then(function () {
//都成功则成功
}, function() {
//只要有失败,则失败
})
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.all/resolve([p1, p2, p3]);
setTimeout(function(){
console.log(result)
/*
Promise {<fulfilled>: Array(3)}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(3)
0: "OK"
1: "Success"
2: "Oh Yeah"
length: 3
[[Prototype]]: Array(0)
*/
},2000)
Promise.race方法的使用
竞赛,谁跑的快,以谁为准执行回调
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');
//调用
const result = Promise.race([p1, p2, p3]);
setTime(function({
console.log(result) //Promise {<fulfilled>: 'Success'}
})
async await
- async后面跟一个函数,表明这个函数是异步执行的,可单独使用
- await后面一定要接promise风格的函数且有resolve返回值,否则返回undefined
- await必须与async配套使用,表示等待await后面的函数执行完毕后再执行后续代码
- async也是基于promise封装的函数,返回值是一个promise对象,也可以调用then方法
- 在await之前的代码属于同步调用,在await之后的代码则会进入异步队列,会在前面的await得到返回值以后再执行后续的代码
let step = (time) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve("test");
}, time);
});
};
async function demo() {
let word = await step(500);
console.log(word);
}
demo();//test
//上诉代码首先创建一个返回promise对象的函数,
//再使用async和await关键词,
//word的值会在await得到修饰函数的返回值后赋值。
async function demo() {
let word1 = await step(500);
console.log(word1); //test
let word2 = await step(1000);
console.log(word2);//test
return "函数执行完成";
}
demo().then((res) => {
console.log(res);//函数执行完成
});