1.修改promise的状态
let p = new Promise((resolve, reject) => {
//1. resolve 函数
// resolve('ok'); // pending => fulfilled (resolved)
//2. reject 函数
// reject("error");// pending => rejected
//3. 抛出错误
// throw '出问题了',rejected;
});
通过throw也可以修改promise状态
2.能否执行多个回调
let p = new Promise((resolve, reject) => {
resolve('OK');
});
///指定回调 - 1
p.then(value => {
console.log(value);
});
//指定回调 - 2
p.then(value => {
alert(value);
});//都可以执行
3.改变状态与指定回调的顺序
1. 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
// 常规: 先指定回调函数, 后改变的状态
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数
}, 1000);
}).then(// 先指定回调函数, 保存当前指定的回调函数
value => {},
reason => {console.log('reason', reason)}
)
2. 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
// 如果先改状态, 后指定回调函数
new Promise((resolve, reject) => {
resolve(1) // 先改变的状态(同时指定数据)
}).then(// 后指定回调函数, 同步执行回调函数
value => {console.log('value2', value)},
reason => {console.log('reason2', reason)}
)
总结:只有当状态改变才会执行回调
4.then方法返回promise结果由什么决定
let p = new Promise((resolve, reject) => {
resolve('ok');
});
//执行 then 方法
let result = p.then(value => {
// console.log(value);
//1. 抛出错误
// throw '出了问题';
//2. 返回结果是非 Promise 类型的对象
// return 521;
//3. 返回结果是 Promise 对象
// return new Promise((resolve, reject) => {
// // resolve('success');
// reject('error');
// });
//不返回,promise的值是undefined
//返回的是pending状态的promise,会中断链式调用
}, reason => {
console.warn(reason);
});
console.log(result);
1.抛出错误,then返回的promise对象是rejected
2.promise内部返回结果是非promise对象,return number/string/boolean,then的返回的promise对象是resolve
3.then的promise返回结果是promise对象,由内部返回的promise对象来绝对then的promise对象的状态
4.then内部不返回值,后面的then调用默认是undefined
5.promise如何串联多个任务
1.promise的then返回一个promise对象,通过链式调用即可
2.通过then串联同步/异步操作
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
return new Promise((resolve, reject) => {
resolve("success");
});
}).then(value => {
console.log(value);
}).then(value => {
console.log(value);
})
6.异常的穿透
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
// reject('Err');
}, 1000);
});
p.then(value => {
// console.log(111);
throw '失败啦!';
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
异常的穿透,在改变状态之后执行then中的回调,then的返回结果是promise,但是改变了promise的状态,是rejected,返回的rejected的promise对象直接穿透到catch中
7.如何中断promise链
有且只有一个方式返回一个pending状态的promise
return new Promise(() => {})
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 1000);
});
p.then(value => {
console.log(111);
//有且只有一个方式
return new Promise(() => {});
}).then(value => {
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
8.错误的捕获
首页我们先要区分几个概念:
第一,reject是用来抛出异常的,catch是用来处理异常的;
第二:reject是Promise的方法,而then和catch是Promise实例的方法(Promise.prototype.then 和 Promise.prototype.catch)。
1. 区别
主要区别就是,如果在then的第一个函数里抛出了异常,后面的catch能捕获到,而then的第二个函数捕获不到。
catch只是一个语法糖而己 还是通过then 来处理的,
大概如下所示字体:
Promise.prototype.catch = function(fn){
return this.then(null,fn);
}
then的第二个参数和catch捕获错误信息的时候会就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会捕获到。
const promise = new Promise((resolve, rejected) => {
throw new Error('test');
});
//此时只有then的第二个参数可以捕获到错误信息
promise.then(res => {
//
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});
//此时catch方法可以捕获到错误信息
promise.then(res => {
//
}).catch(err1 => {
console.log(err1);
});
//此时只有then的第二个参数可以捕获到Promise内部抛出的错误信息
promise.then(res => {
throw new Error('hello');
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});
//此时只有then的第二个参数可以捕获到Promise内部抛出的错误信息
promise.then(res => {
throw new Error('hello');
}, err => {
console.log(err);
});
//此时catch可以捕获到Promise内部抛出的错误信息
promise.then(res => {
throw new Error('hello');
}).catch(err1 => {
console.log(err1);
});
2. 两个捕获方法的比较
// bad
promise
.then(function(data) {
// success
}, function(err) {
// error
});
// good
promise
.then(function(data) { //cb
// success
})
.catch(function(err) {
// error
});
上面代码中,第二种写法要好于第一种写法,理由是第二种写法可以捕获前面then方法执行中的错误,也更接近同步的写法(try/catch)。因此,建议总是使用catch方法,而不使用then方法的第二个参数。