异步编程
JavaScript是基于单线程的事件循环机制构建的,单线程意味着在任何时候只有一个主线程来处理所有任务。
当有异步任务要处理时,主线程会挂起该任务,异步任务处理完成,JavaScript会将该任务加入到一个事件队列中,被放入事件队列的任务回调不会立即执行,而是等当前执行栈中的所有任务执行完毕再去执行。
异步任务有两种类型,微任务和宏任务,每种类型都有自己对应的任务队列。
当执行栈中所有任务执行完毕,会去检查微任务队列是否有事件,如果有,则依次执行完微任务队列所有的事件对应的回调,然后再去宏任务队列取出一个事件,把对应的回调加入到当前执行栈,开始执行,当执行栈所有的任务都执行完毕,检查微任务队列是否有事件存在。
一直重复此过程,这个循环就是事件循环
Promise
在Promise之前通常采用回调模式,回调模式多个方法嵌套会有回调地狱问题。
Promise不会立即开始执行,而是先返回一个表示异步读取操作的Promise对象,未来对这个对象的操作完全取决于Promise的生命周期。
Promise的生命周期:
pending 进行中、fulfilled 异步操作成功完成、rejected 异步操作失败。
当Promise状态改变时,通过then方式采取特定的行动,then方法有两个参数
第一个是当Promise状态变为fulfilled时要调用的函数,第二个是当Promise状态变为rejected时要调用的函数。
let fs = require("fs");
function getData() {
return new Promise((resolve, reject) = >{
fs.readFile('./test.js', 'utf8', (err, data) = >{
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
let promise = getData();
promise.then(data = >{
//完成
console.log(data)
},err = >{
//拒绝
console.error(err)
})
promise.then(data = >{
//完成
console.log(data)
})
promise.then(null, err = >{
//拒绝
console.error(err)
})
promise.then(null, err = >{
//拒绝
console.error(err)
})
//等同于
promise.catch(err = >{
//拒绝
console.error(err)
})
创建未完成的Promise
用Promise构造函数可以创建新的Promise,构造函数只接受一个包含初始化Promise代码的执行器函数,执行器接受两个参数,分别是resolve函数和 reject函数,执行器成功时调用resolve,失败时则调用reject函数。
let fs = require("fs");
function getData() {
return new Promise((resolve, reject) = >{
fs.readFile('./test.js', 'utf8', (err, data) = >{
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
}
创建已处理的Promise
let promise = Promise.resolve(1);
promise.then(value = >{
console.log(value); //1
})
let promise = Promise.reject(1);
promise.catch(value = >{
console.log(value); //1
})
执行器错误
let promise = new Promise((resolve, reject) = >{
throw new Error("hh")
})
promise.catch(error = >{
console.log(error.message) //hh
})
串联Promise
每次调用then()方法或者catch()方法,会返回另一个Promise,只有当第一个Promise完成或者被拒绝,第二个才会被调用。
let p1 = new Promise((resolve, reject) = >{
resolve(1);
})
p1.then(value = >{
console.log(value);
}).then(() = >{
console.log('哈哈');
})
串联Promise捕获错误
let p1 = new Promise((resolve, reject) = >{
resolve(1);
})
p1.then(value = >{
console.log(value);
throw new Error('error');
}).catch((error) = >{
console.log(error.message); //error
})
串联Promise返回值
let p1 = new Promise((resolve, reject) = >{
resolve(2)
});
p1.then(value = >{
console.log(value); //2
return value + 2;
}).then(value = >{
console.log(value); //4
})
let p1 = new Promise((resolve, reject) = >{
reject(2)
});
p1.catch(value = >{
console.log(value); //2
return value + 2;
}).then(value = >{
console.log(value); //4
})
在Promise链中返回Promise
let p1 = new Promise((resolve, reject) = >{
resolve(2);
})
let p2 = new Promise((resolve, reject) = >{
resolve(4);
})
p1.then(value = >{
console.log(value); //2
return p2;
}).then(value = >{
console.log(value); //4
})
Promise.all()
Promise.all()只接收一个数组参数并返回一个Promise,该数组参数里面是多个Promise,只有当数组里面所有Promise状态为已完成时,该返回的Promise状态才会变成已完成
let p1 = new Promise((resolve, reject) = >{
resolve(1);
})
let p2 = new Promise((resolve, reject) = >{
resolve(2);
})
let p3 = new Promise((resolve, reject) = >{
resolve(3);
})
let promise = Promise.all([p1, p2, p3])
promise.then(value = >{
console.log(value); //[1, 2, 3]
})
只要有一个返回拒绝,Promise就会调用catch方法,因为value接收的是值而不是数组,所以只会返回第一个拒绝的value。
let p1 = new Promise((resolve, reject) = >{
reject(1);
})
let p2 = new Promise((resolve, reject) = >{
reject(2);
})
let p3 = new Promise((resolve, reject) = >{
reject(3);
})
let promise = Promise.all([p1, p2, p3])
promise.catch(value = >{
console.log(value); //1
})
Promise.race()
Promise.race()接收的也是一个数组,返回一个Promise,不同的是,这里返回的Promise只会处理数组里面第一个完成状态的Promise,其余的结果会被忽略掉。
let p1 = new Promise((resolve, reject) = >{
setTimeout(() = >{
reject(33);
},0)
})
let p2 = new Promise((resolve, reject) = >{
reject(5);
})
let p3 = new Promise((resolve, reject) = >{
reject(3);
})
let promise = Promise.race([p1, p2, p3])
promise.then(value = >{
console.log(value);
}).catch(value = >{
console.log(value); //5
})
Promise继承
class MyPromise extends Promise {
success(resolve, reject) {
return this.then(resolve, reject);
}
failure(reject) {
return this.catch(reject);
}
}
let p1 = new MyPromise((resolve, reject) = >{
reject(3);
})
p1.success(value = >{
// console.log(value);
}).catch(value = >{
console.log(value); //3
})