likes
comments
collection
share

Promise基础

作者站长头像
站长
· 阅读数 45

Promise基础

Promise基础

一、Promise定义

Promise:承诺者模式:它是ES6新增的一个内置类,基于Promise可以有效管理"异步编程",避免回调地狱

语法

executor函数

  • let p=new Promise([executor]) 语法 

    • p是它的实例

    •  [executor]是一个函数,传递的不是函数会报错

 p.proto===Promise.prototype[所属类的原型]

  • 实例私有属性

    • [[PromiseState]]:"pending"  

      • promise实例的状态有三种

        • pending准备状态  

        • fulfilled/resolved成功状态  

        • rejected失败状态

      • 最初的状态是pending,后期基于某些操作可以把状态改变为fulfilled或者rejected

      • (但是一但状态变为成功或者失败,则再也不能修改其状态了)

    • [[PromiseResult]]:undefined

      • [[PromiseResult]]存放的是成功的结果或者失败的原因!
  •  实例公有属性

then / catch / finally / Symbol.toStringTag="Promise" [原型上]

Promise基础

二、状态改完有什么用

  • 基于then可以存放两个函数  p.then(onfulfilled,onrejected)

  • 当我们把状态修改为fulfilled成功态,则会把onfulfilled这个函数执行,相反,我们把状态修改为rejected失败态,则会把onrejected这个函数执行...

  • 并且会把[[PromiseResult]]作为实参值,传递给onfulfilled/onrejected

三、怎么改状态

  • new Promise的时候,会立即把传递进来的executor[承诺执行人]函数执行,并且会给executor传递两个实参进来

我们会用两个形参变量接收resolve/reject,并且值是两个函数

  • 当我们执行resolve,promise实例状态变为fulfilled成功,传递的值就是成功的结果,赋值给[[PromiseResult]];

同理,只要把reject执行,promise实例状态变为rejected失败,传递的值就是失败的原因!

  • 如果executor函数执行报错了,则实例的状态也是rejected失败,失败原因是就是错误信息!

new Promise产生的实例,他的状态是成功还是失败,取决于“resolve/reject执行 或者 executor执行是否报错”

//========================>基础语法
let p=new Promise(function exector(resolve,reject){
	 console.log(1);//先输出1
   resolve('OK');//promise实例状态变为fulfilled 
});
console.log(p);
//p.then(onfulfilled,onrejected)
p.then(function onfulfilled(result){
		//当状态为fulfilled的时候 会执行此函数
  	//result 存放的是成功结果 OK
},function onrejected(reason){
	 //当状态为rejected的时候,会执行此函数
   //reason 失败的原因
});

四、Promise的then

new Promise((resolve, reject) => {
    $.ajax({
        url: './api/data1.json',
        success(result) {
            resolve(result); //成功的时候把=》实例状态成功
        },
        error(reason) {
            reject(reason); 
        }
    });
}).then(result => {
    console.log('请求成功', result);//成功做什么
}, reason => {
    console.log('请求失败', reason);//失败做什么
}); 

//========================setTimeout异步

new Promise((resolve, reject) => {
    setTimeout(() => {
        let ran = Math.random();
        if (ran > 0.5) resolve('OK');
        reject('NO');
    }, 1000);
}).then(result => {
    console.log('请求成功', result);
}, reason => {
    console.log('请求失败', reason);
}); 

4.1 多次.then

我们可以基于 “promise实例.then” 存放多个onfulfilled/onrejected方法,状态变为成功或者失败,

存放的每一个对应的方法都会被执行

let p1 = new Promise((resolve, reject) => {
    resolve(100);//实例状态变为成功
});
p1.then(result => {
    console.log(`成功:${result}`);//输出成功,100
}, reason => {
    console.log(`失败:${reason}`);
});
p1.then(result => {
    console.log(`成功:${result}`);//输出成功,100
}, reason => {
    console.log(`失败:${reason}`);
}); 

4.2 new Promise产生的是实例 &执行then方法返回的实例

  • new Promise产生的实例,他的状态是成功还是失败,取决于“resolve/reject执行 或者 executor执行是否报错”

  • 每一次执行THEN方法,不仅存放了onfulfilled/onrejected方法,而且还会返回一个“全新的promise实例”

    • 新实例p2的状态和值由谁来决定呢?

      • 首先看返回值是否是一个新的Promise实例

      • 不论onfulfilled/onrejected这两个方法执行的是哪一个,我们只看执行是否报错;

        • 如果报错,则p2的状态是失败态rejected,值是报错原因!

        • 如果不报错,则p2的状态是成功态fulfilled,值是函数的返回值!

let p1 = new Promise((resolve, reject) => {
    reject(0);
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`);
    return 1000;
}, reason => {
    console.log(`失败:${reason}`); //失败 0 //没有报错代码 所以新实例的状态为成功
    return -1000;
});
let p3 = p2.then(result => {
    console.log(`成功:${result}`); //成功 -1000
    throw new Error('xxx');//因为有错误信息,所以这个返回的实例是失败状态
}, reason => {
    console.log(`失败:${reason}`);
});
p3.then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失败:${reason}`); //失败 Error:xxx //失败就会执行reason
});

4.3 .then 返回值是一个新的promise实例的特殊情况

特殊情况:我们之前说,不论onfulfilled/onrejected执行,只要不报错,则新实例p2的状态就是成功,只要报错就是失败...但是这里有一个特殊的情况:“执行不报错,但是返回值是一个新的promise实例,这样返回值的这个promise实例是成功还是失败,直接决定了p2是成功还是失败”

let p1 = new Promise((resolve, reject) => {
    resolve(100);
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`); //成功 100
    return new Promise((resolve, reject) => reject(-1000)); //执行了reject 所以状态为失败
}, reason => {
    console.log(`失败:${reason}`);
    return -1000;
});
p2.then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失败:${reason}`); //失败:-1000
});
let p1 = new Promise((resolve, reject) => {
    reject(0);//执行了失败的方法
});
let p2 = p1.then(result => {
    console.log(`成功:${result}`);
    return new Promise((resolve, reject) => reject(-1000));
}, reason => {
    console.log(`失败:${reason}`); //失败:0 //p1执行的是reject
    return new Promise((resolve, reject) => resolve(1000)); //成功
});
p2.then(result => {
    console.log(`成功:${result}`); //成功:1000
}, reason => {
    console.log(`失败:${reason}`);
}); 

五、Promise的then链机制

Promise基础

Promise中的then链机制:因为每一次.then都会返回一个新的promise实例,所以我们就可以持续.then下去了

而且因为实例诞生的方式不同,所以状态判断标准也不同

  第一类 new Promise 出来的实例

  • 执行的是 resolve 还是 reject 决定状态
  • executor函数执行是否报错

  第二类 :. then 返回的新实例

     .then执行会返回一个全新的promise实例“p2”:不论是then中的onfulfilled还是onrejected执行

  • 首先看返回值是否为新的promise实例,

    • 如果返回的是新的promise实例,则新的promise实例的状态和值,直接决定了.then返回的实例的状态和值

    • 如果不是,则只看执行是否报错「不报错状态就是成功,值就是函数返回值;报错则状态就是失败,值就是失败原因」

第三类 :把Promise当做对象

  • Promise.resolve(100) 返回一个状态是成功,值是100的新promise实例【值就是你传递实参进来的实参信息】

  •  Promise.reject(0)  返回一个状态是失败,值是0的新promise实例

只要实例的状态和值我们分析好,则 .then(onfulfilled,onrejected) 存放的方法,哪一个执行我们就知道了

let p1 = new Promise((resolve, reject) => {
    resolve(1);//更改p1的状态
    reject(0);
});
let p2 = p1.then(function onfulfilled(result) {
   //执行onfulfilled =>没有报错 没有返回值 则p2的状态是成功 值是undefined
}, function onrejected(reason) {
	
});
p2.then(function onfulfilled(result) {
   	console.log(result);//结果是undefined
}, function onrejected(reason) {

}); 

思考题

Promise.resolve(100).then(result => {
    console.log(`成功:${result}`);//100
    return result / 10;
}, reason => {
    console.log(`失败:${reason}`);
    return Promise.resolve(200);
}).then(result => {
    console.log(`成功:${result}`);//10
    return Promise.reject(300);
}, reason => {
    console.log(`失败:${reason}`);
    return reason / 20;
}).then(result => {
    console.log(`成功:${result}`);
    return 0;
}, reason => {
    console.log(`失败:${reason}`);//300
    return 1;
}).then(result => {
    console.log(`成功:${result}`);//成功1
}, reason => {
    console.log(`失败:${reason}`);
});

Promise基础

Promise.resolve(Promise.reject(100)); //传递的值是失败的promise实例

// 状态:fulfilled
// 值:新的实例 -> 状态:rejected  值:100 */
Promise.resolve(10).then(result => {
    console.log(`成功:${result}`); //成功 10
    return Promise.resolve(Promise.reject(100));
   //如果实例的状态是成功状态,需要把它的值再次处理一遍,以最后一个值处理的结果为准
}).then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失败:${reason}`); //失败:100
}); 

//===========================
Promise.resolve(10).then(result => {
    console.log(`成功:${result}`); //成功:10
    return Promise.reject(Promise.resolve(100));
}).then(result => {
    console.log(`成功:${result}`);
}, reason => {
    console.log(`失败:${reason}`); //失败:[object Promise]
});

以上总结:如果执行onfulfilled或者onrejected的时候,返回的值是是一个promise实例“@P”,

我们之前说“@P”是成功还是失败,直接决定了“p2(.then返回的新实例)”是成功还是失败...但是这样是不严谨的,

  • 按照官方规范要求:

    • 如果@P是成功状态,需要把它的值再次处理一遍...

    • 如果@P是失败的,直接认定为失败的状态,不需要把失败的值再次处理...

5.1 then链的穿透性(顺延)

正常情况下,.then的时候会传递两个函数onfulfilled/onrejected,但是有些时候,我们是不传递其中的某个函数的,这种情况下我们需要采取“顺延策略”:找到下一个then中对应状态的函数执行

例如:.then(null,onrejected) 【只处理失败】或者 .then(onfulfilled)【只处理成功】

Promise.reject(0).then(result => {
    console.log(`成功:${result}`);
    return 1;
}).then(result => {
    console.log(`成功:${result}`);
    return 2;
}).then(result => {
    console.log(`成功:${result}`);
    return 3;
}, reason => {
    console.log(`失败:${reason}`); //失败:0
});

//==================
Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    throw '我失败了'; //自己抛出异常
}).then(result => {
    console.log(`成功:${result}`);
    return 2;
}).then(result => {
    console.log(`成功:${result}`);
    return 3;
}, reason => {
    console.log(`失败:${reason}`); //失败:我失败了 顺延至最后一个reason
});

//======================
Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    return 1;
}).then(result => {
    console.log(`成功:${result}`); //成功:1
    return Promise.reject('NO');
}).then(null, reason => {
    console.log(`失败:${reason}`); //失败:NO
}); 

5.2 Promise.catch

 .catch(onrejected) 相当于==> .then(null,onrejected)

真实项目中,我们经常:then中只传递onfulfilled,处理状态是成功的事情;在then链的末尾设置一个catch,处理失败的事情(依托于then链的穿透机制,无论最开始还是哪个then中,出现了让状态为失败的情况,都会顺延到最末尾的catch部分进行处理)

Promise.resolve(100).then(result => {
    console.log(`成功:${result}`); //成功:100
    return 1;
}).then(result => {
    console.log(`成功:${result}`); //成功:1
    return Promise.reject('NO');
}).catch(reason => {
    console.log(`失败:${reason}`); //失败:NO
});
转载自:https://juejin.cn/post/7177731524962287673
评论
请登录