为什么要有promise?
因为promise可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。
1.promise为了解决回调地狱出现,刚开始我们用setTimeOut,把异步按照你期望的顺序执行时(类似于同步),程序多了就会造成很多个setTimeOut嵌套,嵌套的特别深(有点类似栈),就造成了回调地狱。比如:
var sayhello = function (name, callback) {
setTimeout(function () {
console.log(name);
callback();
}, 1000);
}
sayhello("first", function () {
sayhello("second", function () {
sayhello("third", function () {
console.log("end");
});
});
});
//输出: first second third end
promise解决办法:.then的链式写法,因为promise返回也是promise对象
var sayhello = function (name) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(name);
resolve(); //在异步操作执行完后执行 resolve() 函数
}, 1000);
});
}
sayhello("first").then(function () {
return sayhello("second"); //仍然返回一个 Promise 对象
}).then(function () {
return sayhello("third");
}).then(function () {
console.log('end');
}).catch(function (err) {
console.log(err);
})
//输出:first second third end
2.为了避免界面冻结
一般可能你会想为什么我不用同步呢,代码写起来也简单,执行程序的顺序是啥我就写成啥,不就好了吗,区别就是下面说的:
你可以异步操作,不同于同步,如果客户发起请求,同步则是系统还在做他之前的事,做完才会响应客户的请求;而异步则是客户发起请求,系统就会先去处理客户的请求,界面就不会卡住,这个也就是为什么用异步,因为他处理请求要更加快。
异步操作常用场合:
事件监听:
document.getElementById('#start').addEventListener('click', start, false);
function start() {
// 响应事件,进行相应的操作
}
回调:
success (res) {
// 这里可以监听res返回的数据做回调逻辑的处理
}
nodeJS对异步的依赖进一步加剧了
无阻塞高并发,是nodeJS的招牌,要达到无阻塞高并发异步是其基本保障。
一般情况我们一次性调用API就可以完成请求。有些情况需要多次调用服务器API,就会形成一个链式调用,比如为了完成一个功能,我们需要调用API1、API2、API3,依次按照顺序进行调用,这个时候就会出现回调地狱的问题
promise有三个状态:
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
resolve作用是:将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
new Promise(resolve => {
setTimeout(() => {
resolve('hello')
}, 2000)
}).then(res => {
console.log(res)
})
promise.then得到promise解决状态的值;
.then()
1、接收两个函数作为参数,分别代表fulfilled(成功)和rejected(失败)
2、.then()返回一个新的Promise实例,所以它可以链式调用
3、当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行
4、状态响应函数可以返回新的promise,或其他值,不返回值也可以我们可以认为它返回了一个null;
5、如果返回新的promise,那么下一级.then()会在新的promise状态改变之后执行
6、如果返回其他任何值,则会立即执行下一级.then()
promise.catch得到promise拒绝状态的值
得到promise拒绝状态的值有俩种方式:
第一种:reject('错误信息').then(() => {}, () => {错误处理逻辑})
第二种:throw new Error('错误信息').catch( () => {错误处理逻辑})
catch也会返回一个promise实例,并且是resolved状态
throw new Error为rejected状态,后面如果有.then不会执行,直到等到catch。
Promise.all() 批量执行
Promise.all([p1, p2, p3])用于将多个promise实例,包装成一个新的Promise实例,返回的实例就是普通的promise
它接收一个数组作为参数
数组里可以是Promise对象,也可以是别的值,只有Promise会等待状态改变
当所有的子Promise都完成,该Promise完成,返回值是全部值得数组
有任何一个失败,该Promise失败,返回值是第一个失败的子Promise结果