Promise 是什嘛
ES6 语法规范中新加的内置类,用来处理 js 中异步编程的,而我们所谓的 Promise 设计模式,就是基于 promise 对异步操作进行管理 ;主要解决回调地狱 promose 是一个内置类,所以创建一个 promise:new Promise([executor]): 第一个执行函数必须传递,这里的 executor 是一个回调函数下面简称 exe
new promise 的时候就会把 exe 执行,创建 promise 的一个实例(exe 是 promise 类的一个回调函数,promise 内部会把它执行) promise 不仅把 exe 执行,而且还给 exe 传递两个参数(两个参数也是函数类型) resolve 函数:它执行代表 promise 处理的异步事情是成功的,把 promise 的状态改为 fulfilled reject 函数:它执行代表 promise 处理的异步事情是失败的,把 promise 的状态改为 rejected exe 函数中放的就是当前要处理的异步操作事情 let promiseExamp = new Promise((resolve, reject) => {这里一般存放的都是我们即将要处理的异步任务,任务成功我们执行 resolve,任务失败我们执行 reject(当然写同步的也可以)}
异步编程中的回调地狱
一个回调函数嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数再嵌一个回调函数… 就是回调地狱。 一个小例子: 从服务器获取某个学生的基本信息 (score-id) -> 基于分数的 ID 获取到当前学生各项成绩 -> 基于某一项成绩获取他在学校的排名
promise 三个状态: pending 进行中 fulfilled 成功 rejected 失败
改变状态有两种可能 pending–>fulfilled pending–> rejected ; 下面展示一些 内联代码片
。
let p = new Promise(function (resolve, reject) {
// resolve(); // 调用resolve代表执then中的第一个回调,resolve代表的是成功态
reject(); // // 调用reject ,就代表执行then的的第二个回调;失败态
}).then(function () {
console.log(1);
}, function () {
console.log(2);
}).then(function () {
}, function () {
})
promise 写法示例
let p = new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
console. log ( "买菜" ) ;
resolve ( ) ;
} , 3000 )
} ) . then ( function ( ) {
return new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
console. log ( "洗菜" ) ;
resolve ( )
} , 2000 )
} )
} ) . then ( function ( ) {
return new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
console. log ( "做菜" ) ;
resolve ( )
} , 1000 )
} )
} )
Promise.prototype.then()
then : 在Promise的原型上的一个方法; p.then 也会默认返回一个promise 实例,而且默认是成功的;如果在then的回调函数中也返回一个promise 实例,那么这个promise 实例就会覆盖默认返回的实例影响下一个then中的回调函数; 如果return promise 的实例那么下面的then就会受实例的影响,在实例执行完后再执行then 如果没有return promise 的实例那么下面的then就不受影响,直接执行 示例1
< script>
let p = new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
if ( Math. random ( ) > 0.5 ) {
resolve ( 100 ) ;
} else {
reject ( ) ;
}
} , 1000 )
} )
p. then ( function ( a) {
console. log ( a) ;
return new Promise ( function ( resolve, reject) {
resolve ( ) ;
} ) ;
} , function ( ) {
console. log ( "不买" ) ;
} ) . then ( function ( ) {
console. log ( "成功" )
} , function ( ) {
console. log ( "失败" )
} )
< / script>
let p = new Promise ( function ( resolve, reject) {
resolve ( )
} ) ;
p. then ( function ( ) {
return new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
console. log ( 1 ) ;
resolve ( ) ;
} , 2000 )
} )
} , function ( ) {
} ) . then ( function ( ) {
console. log ( 2 ) ;
} )
Promise.prototype.catch()
一般来说,不要在then中定义第二个reject函数;一般使用catch;理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)。 如果在then中抛出错误,就会执行下面的catch 如果then中有一个异常,也会抛出错误只要then链中有一个异常,就会执行最后的catch;只要在then中有失败的回调,就不再执行最后的catch了只要其中一个then的回调失败,就不再执行下面的then中的回调,而是直接走catch
let p = new Promise ( function ( resolve, reject) {
resolve ( ) ;
} )
p. then ( function ( ) {
console. log ( 1 ) ;
} ) . then ( function ( ) {
console. log ( 3 ) ;
} ) . then ( function ( ) {
console. log ( a) ;
} ) . catch ( function ( ) {
console. log ( 2 ) ;
} )
Promise.prototype.finally()
promise 的finally 是不管成功还是失败,都会执行的回调 这是会等到promise实例状态改变以后会触发的回调,是一个异步的;
let p = new Promise(function(resolve,reject){
resolve();
})
p.then(function(){
console.log(1);
console.log(a);
}).catch(function(){
console.log(55);
}).finally(function(){
// 这是会等到promise实例状态改变以后会触发的回调,是一个异步的;
console.log(1000);
})
console.log(999);
//999 55 1000
Promise.all()
Promise.all : 用于多个实例,返回一个新promise实例 全部成功状态才是成功,只要有一个失败状态就是失败 如果不是Promise 实例,就会先调用下面讲到的Promise.resolve()方法,将参数转为 Promise 实例,再进一步处理。
let p1 = new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
reject ( 100 ) ;
} , 3000 )
} )
let p2= new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
reject ( 200 ) ;
} , 2000 )
} )
let p3= new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
resolve ( 300 ) ;
} , 4000 )
} ) ;
let p = Promise. all ( [ p1, p2, p3] )
p. then ( function ( data) {
console. log ( data) ;
} ) . catch ( function ( data) {
console. log ( data) ;
} )
Promise.race()
Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。 Promise.race()方法的参数与Promise.all()方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve()方法,将参数转为 Promise 实例,再进一步处理。
let p1 = new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
reject ( 100 ) ;
} , 13000 )
} )
let p2= new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
reject ( 200 ) ;
} , 12000 )
} )
let p3= new Promise ( function ( resolve, reject) {
setTimeout ( function ( ) {
resolve ( 300 ) ;
} , 4000 )
} ) ;
let p = Promise. race ( [ p1, p2, p3] )
p. then ( function ( ) {
console. log ( "成功" ) ;
} ) . catch ( function ( ) {
console. log ( "失败" ) ;
} )
打印结果 是 成功 因为p3先执行完
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
Promise.resolve()
Promise.resolve: 将一个对象转成一个promise的实例;返回值可以调用then方法
Promise.resolve("foo").then(function(){
})
new Promise(function(resolve,reject){
resolve("foo")
});
let p = Promise.resolve();
p.then(function(){
})
ajax的串行与解决
只有第一个请求成功才能执行第二个,第二个成功才能执行第三个,最后一个请求成功后拿到了每一次请求的所有数据。 例如:
$. ajax ( {
url: '/baseInfo' ,
method: 'GET' ,
data: {
name: 'zhanglu'
} ,
success: result => {
let scoreId = result. scoreId;
$. ajax ( {
url: '/scoreInfo' ,
method: 'GET' ,
data: {
id: scoreId
} ,
success: result => {
let chinese = result. chinese;
$. ajax ( {
url: '/paiming' ,
method: 'GET' ,
data: {
num: chinese
} ,
success: result => {
}
} ) ;
}
} ) ;
}
} ) ;
let p = new Promise ( function ( resolve, reject) {
resolve ( )
} ) ;
p. then ( function ( ) {
return new Promise ( function ( resolve, reject) {
$. ajax ( {
url: '/baseInfo' ,
method: 'GET' ,
data: {
name: 'zhanglu'
} ,
success: result => {
let scoreId = result. scoreId;
resolve ( scoreId )
}
} )
} )
} ) . then ( function ( value) {
return new Promise ( function ( resolve, reject) {
$. ajax ( {
url: '/scoreInfo' ,
method: 'GET' ,
data: {
name: 'zhanglu'
} ,
success: result => {
let scoreId = result. scoreId;
resolve ( scoreId )
}
} )
} )
} ) . then ( res=> {
... ...
} )
ajax的并行与解决
let chi = 100 ,
eng = 12 ,
math = 98 ;
let chiPai,
engPai,
mathPai;
let count = 0 ;
function func ( ) {
if ( count >= 3 ) {
}
}
$. ajax ( {
url: '/pai ? chi = ' + chi,
success: result => {
chiPai = result;
count++ ;
func ( ) ;
}
} ) ;
$. ajax ( {
url: '/pai ? eng = ' + eng,
success: result => {
engPai = result;
count++ ;
func ( ) ;
}
} ) ;
$. ajax ( {
url: '/pai ? math = ' + math,
success: result => {
mathPai = result;
count++ ;
func ( ) ;
}
} ) ;
function ajax1 ( ) {
return new Promise ( resolve => {
$. ajax ( {
url: '/api1' ,
success: resolve
} ) ;
} ) ;
}
function ajax2 ( ) {
return new Promise ( resolve => {
$. ajax ( {
url: '/api2' ,
success: resolve
} ) ;
} ) ;
}
function ajax3 ( ) {
return new Promise ( resolve => {
$. ajax ( {
url: '/api3' ,
success: resolve
} ) ;
} ) ;
}
let p = Promise. all ( [ ajax1 , ajax2, ajax3] )
p. then ( function ( data) {
console. log ( data) ;
} ) . catch ( function ( data) {
console. log ( data) ;
} )
自己简单封装一个promise
let p = new MyPromise(function (resolve,reject) { //p1
// resolve形参可以执行;所以该实参一定是个函数
// resolve,reject : 改变当前实例的状态
resolve()
});
p.then(function () { //p 是promise的实例 .then可以执行说明then是原型链上的方法
return new Promise(function (resolve,reject) { // p2
resolve(); // 执行p2事件池中的方法;p2事件池中有个p1 的resolve,p1的resolve执行;会把p1成功事件池中的方法执行;
})
})
// 第一个resolve 要执行p这个实例中成功事件池中的方法;这是一个异步的操作;暂时异步事件池中的方法是不执行;
// 第二个resolve : 执行p2事件池中的方法;p2事件池中有个p1 的resolve,p1的resolve执行;会把p1成功事件池中的方法执行;
// 第一个then : 把then中的方法放入到p的成功事件池中;并且返回一个p1的promise实例;
// 第二个then :p1.调用的then;把then中放到了p1.的成功事件池中;
< script>
class MyPromise {
constructor ( excutor) {
this . state = "pending" ;
this . fulfilledEvent = [ ] ;
this . rejectedEvent= [ ] ;
let resolve = ( result) => {
if ( this . state!== "pending" ) return ;
this . state= "fulfilled" ;
clearTimeout ( this . timer) ;
this . timer = setTimeout ( ( ) => {
this . fulfilledEvent. forEach ( item=> {
if ( typeof item=== "function" ) {
item ( result)
}
} )
} , 0 )
} ;
let reject = ( result) => {
if ( this . state!== "pending" ) return ;
this . state= "rejected" ;
clearTimeout ( this . timer) ;
this . timer = setTimeout ( ( ) => {
this . rejectedEvent. forEach ( item=> {
if ( typeof item=== "function" ) {
item ( result)
}
} )
} , 0 )
} ;
try {
excutor ( resolve, reject)
} catch ( e) {
reject ( e) ;
}
}
then ( resolveFn, rejectFn) {
if ( resolveFn=== undefined) {
resolveFn = ( ) => { } ;
}
if ( rejectFn=== undefined) {
rejectFn = ( ) => {
throw new Error ( ) ;
}
}
return new MyPromise ( ( resolve, reject) => {
this . fulfilledEvent. push ( ( result) => {
try {
let x = resolveFn ( result) ;
x instanceof MyPromise ? x. then ( resolve, reject) : resolve ( ) ;
} catch ( e) {
reject ( e) ;
}
} ) ;
this . rejectedEvent. push ( ( result) => {
try {
let x = rejectFn ( result) ;
x instanceof MyPromise ? x. then ( resolve, reject) : resolve ( ) ;
} catch ( e) {
reject ( e)
}
} ) ;
} )
}
}
let p = new MyPromise ( function ( resolve, reject) {
setTimeout ( function ( ) {
resolve ( 1 )
} , 2000 )
} )
p. then ( function ( val) {
} , function ( ) {
} ) . then (
function ( ) {
}
)
< / script>