Promise 有什么用+学习入门
简介
最开始我是想了解bluebird,后来发现原来要了解bluebird,就先需要了解Promise,所以本节也是了解Promise的基本用法
学习这个有什么作用
1、可以减少很多callback回调的方法,减少层层的嵌套,让代码看起来更加的舒服。
2、针对代码里面存在异步方法时,可以等到异步方法执行完毕了再继续执行后面代码。
基本用法
Promise对象是一个构造函数,当我们要使用Promise,需要new一下
var promise = new Promise(function(resolve, reject) {
//这里写你的主要代码
});
Promise构造函数接受一个函数作为参数,这个函数里面携带了二个方法
resolve与reject,当我们执行操作成功的时候,我们去调用resolve方法,失败的时候我们调用reject方法。为什么要这样规定呢?因为Promise存在三种状态,分别是
pending(进行中) ,fulfilled(已成功),rejected(已失败)
当我们调用promise时候,它就已经是处于进行中了,状态只能从pending-->fulfilled或者是pending-->rejected这二种情况
function testFunction() {
return new Promise(function(resolve,reject){
console.log('你好世界');
});
}
var promise = testFunction();//立即执行
你好世界.png
可以看出,只要testFunction()方法一但调用,就会立即的执行。
更进一步then()用法,链式的使用
我们写代码的时候,代码逻辑程序基本上是从上到下,就像河流一样,从高处往低处流淌。
function methond1(){
var p = new Promise(function(resolve, reject){
resolve("我是第一个方法");
});
return p;
}
function methond2(){
var p = new Promise(function(resolve, reject){
resolve("我是第二个方法");
});
return p;
}
function methond3(){
var p = new Promise(function(resolve, reject){
resolve("我是第三个方法");
});
return p;
}
function methond4(){
var p = new Promise(function(resolve, reject){
resolve("我是第四个方法");
});
return p;
}
methond1()
.then(function(data){
console.log(data);
return methond2();
})
.then(function(data){
console.log(data);
return "我不调用第三个方法了";
}).then(function(data){
console.log(data);
return methond4();
}).then(function(data){
console.log(data);
}).then(function(data){
console.log("德玛西亚");
}).then(function(data){
console.log("艾欧里亚");
});
链式调用.png
从上面的代码里面可以说明几点:
1、使用return 可以调用方法,也可以把参数传递到下面
2、当我把参数放到resolve里面,可以在function(data)里面直接获取到
3、通过then可以直接链式逻辑写代码
4、data是上一个逻辑里面的数据
我们也可以看看其他博主大神写的
下面我直接复制吕大豹代码,我稍做了修改
function getNumber() {
var p = new Promise(function (resolve, reject) {
var num = Math.ceil(Math.random() * 10); //生成1-10的随机数
if (num <= 8) {
resolve(num);
} else {
reject('数字太大了');
}
});
return p;
}
getNumber().then(function(data){
console.log('resolved');
console.log(data);
},
function(reason){
console.log('rejected');
console.log(reason);
}
);
数字正确调用.png
数字不正确调用.png
上面的代码可以知道then里面可以写2个方法,第一个方法是成功时候调用,第二个个是失败的时候调用。
如果我直接.then(),不像上面的代码会怎样呢?
function methond1() {
var p = new Promise(function (resolve, reject) {
resolve("我是第一个方法");
});
return p;
}
function methond2() {
var p = new Promise(function (resolve, reject) {
resolve("我是第二个方法");
});
return p;
}
function methond3() {
var p = new Promise(function (resolve, reject) {
resolve("我是第三个方法");
});
return p;
}
function methond4() {
var p = new Promise(function (resolve, reject) {
resolve("我是第四个方法");
});
return p;
}
methond1()
.then(function(data){
console.log(data);
return methond2();
}).then(function(){ //这里我没有data了
return "我不调用第三个方法了";
}).then(function(data){
console.log(data);
return methond4();
}).then(function(data){
console.log(data);
}).then(function(data){
console.log("德玛西亚");
}).then(function(data){
console.log("艾欧里亚");
}).catch(function(reason){
console.log(reason);
});
直接then().png
可以看到方法继续执行,没有受到任何的干扰。
又如果我注释掉return会怎样?
methond1()
.then(function(data){
console.log(data);
return methond2();
}).then(function(data){
console.log(data);
//return "我不调用第三个方法了"; 这里我注释了
}).then(function(data){
console.log(data);
return methond4();
}).then(function(data){
console.log(data);
}).then(function(data){
console.log("德玛西亚");
}).then(function(data){
console.log("艾欧里亚");
}).catch(function(reason){
console.log(reason);
});
去掉了return.png
可以看到去掉return后,继续执行代码。
catch捕获异常
当我们的程序从上到下一直执行的时候,执行到一半出现异常了,就可以使用catch来捕获
function runAsync1() {
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('异步任务1执行完成');
resolve('随便什么数据1');
}, 1000);
});
return p;
}
function runAsync2() {
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('异步任务2执行完成');
resolve('随便什么数据2');
}, 2000);
});
return p;
}
function runAsync3() {
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('异步任务3执行完成');
resolve('随便什么数据3');
}, 2000);
});
return p;
}
function methond1() {
var p = new Promise(function (resolve, reject) {
resolve("我是第一个方法");
});
return p;
}
function methond2() {
var p = new Promise(function (resolve, reject) {
resolve("我是第二个方法");
});
return p;
}
function methond3() {
var p = new Promise(function (resolve, reject) {
resolve("我是第三个方法");
});
return p;
}
function methond4() {
var p = new Promise(function (resolve, reject) {
resolve("我是第四个方法");
});
return p;
}
methond1()
.then(function(data){
console.log(data);
return methond2();
}).then(function(data){
console.log(data);
return "我不调用第三个方法了";
}).then(function(data){
console.log(data);
console.log(bbbbbbbbbbb); //这里的bbbbbbbbbbb我没有定义它,捕获异常
return methond4();
}).then(function(data){
console.log(aaaaaaa);//这里我也没有定义它
}).then(function(data){
console.log("德玛西亚");
}).then(function(data){
console.log("艾欧里亚");
}).catch(function(reason){//这里是捕获异常
console.log(reason);
});
异常捕获.png
从上面的图片结果来看我们可以总结下:
1、当出现程序异常,会直接进入catch。
2、当出现异常,后面的代码不会继续执行。
链接中途捕获异常
methond1()
.then(function(data){
console.log(data);
return methond2();
})
.then(function(data){
console.log(data);
return Promise.reject(new Error("啦啦啦啦"));
}).then(function(data){
console.log(data);
return methond4();
}).then(function(data){
console.log(data);
}).then(function(data){
console.log("德玛西亚");
}).then(function(data){
console.log("艾欧里亚");
}).catch(function(reason){
console.log(reason);
});
链接中途捕获异常.png
从上面的图片结果来看我们可以总结下:
1、当链接中途发生异常后续不再执行
异步全部执行完毕了再回调-->all方法
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,比如这
var promise = Promise.all([pro1,pro2, pro3]);
从上面代码我们知道,他接受一数组,pro1,pro2,pro3 都是要Promise 实例,promise 的状态由pro1,pro2, pro3共同决定,只要有1个失败了,那么就是失败的
function methond1(){
var p = new Promise(function (resolve, reject) {
setTimeout(console.log("methond1"),2000);
resolve("100");
});
return p;
}
function methond2(){
var p = new Promise(function (resolve, reject) {
setTimeout(console.log("methond2"),2000);
resolve("200");
});
return p;
}
function methond3(){
var p = new Promise(function (resolve, reject) {
setTimeout(console.log("methond3"),2000);
resolve("300");
});
return p;
}
Promise.all([methond1(), methond2(), methond3()])
.then(function(results){
console.log(results);
});
all方法的使用.png
从最后的结论中,我们可以总结以下
1、最后的100,200,300的数据显示是一个集合,并且当所有的promise执行完后才显示的。
then()里面遇见return 后续then()继续执行
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
return; //这里打了return了
console.log("Task C");
}
function onRejected(error) {
console.log("Catch Error: A or B", error);
}
function finalTask() {
console.log("Final Task");
}
var promise = Promise.resolve();
promise
.then(taskA)
.then(taskB)
.then(finalTask)
.catch(onRejected);
后续return继续执行.png
手动结束/终止链接调用
function taskA() {
console.log("Task A");
}
function taskB() {
console.log("Task B");
return Promise.reject(new Error("手动抛出异常"));
}
function onRejected(error) {
console.log(error)
}
function finalTask() {
console.log("Final Task");
}
var promise = Promise.resolve();
promise
.then(taskA)
.then(taskB)
.then(finalTask)
.catch(onRejected);
手动抛异常.png
我又参考了其他文献新增总结如下
- 使用
promise.then(onFulfilled, onRejected)
的话- 在
onFulfilled
中发生异常的话,在onRejected
中是捕获不到这个异常的。
- 在
- 在
promise.then(onFulfilled).catch(onRejected)
的情况下-
then
中产生的异常能在.catch
中捕获
-
-
.then
和.catch
在本质上是没有区别的- 需要分场合使用。
参考与摘要:
https://www.cnblogs.com/lvdabao/p/es6-promise-1.html 说的很好这一篇。
https://wohugb.gitbooks.io/ecmascript-6/content/docs/promise.html 入门