Promise 是一个构造函数,它自身拥有all、reject、resolve这几个眼熟的方法, 原型上有then、catch等一样熟悉的方法。 因此,在开始一个Promise的时候,先new一个吧:javascript
let p = new Promise((resolve, reject)=> {
setTimeout(()=> {
resolve('执行完成')
}, 1000)
})
复制代码
Promise是一个构造函数,接受一个回调函数做为参数,回调函数的参数是resolve
、reject
。分别表示异步操做执行成功后的回调函数和异步操做执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不许确,按照标准来说,resolve
是将Promise的状态置为fullfiled,reject
是将Promise的状态置为rejected。不过在咱们开始阶段能够先这么理解,后面再细究概念。前端
在上面的代码中,咱们执行了一个异步操做,也就是setTimeout,1秒后,输出“执行完成”,而且调用resolve方法。java
行代码,会在2秒后输出“执行完成”。注意!我只是new了一个对象,并无调用它,咱们传进去的函数就已经执行了,这是须要注意的一个细节。因此咱们用Promise的时候通常是包在一个函数中,在须要的时候去运行这个函数,如:dom
function runAsync() {
let p = new Promise((resolve, reject)=> {
setTimeout(()=> {
console.log('执行完成');
resolve(123);
}, 2000)
})
return p;
}
runAsync()
复制代码
这时候你应该有个疑问:包装这么一个函数有什么做用?异步
在咱们包装好的函数最后,会return出Promise对象 p
,也就是说,执行这个函数咱们获得了一个Promise对象。Promise对象上有then、catch方法,这这个时候就能够用到它们了,看下面的代码:函数
runAsync().then((result)=> {
console.log(result);
// 作其余操做
})
复制代码
在runAsync()的返回上直接调用then
方法,then
接收一个参数,是函数,而且会拿到咱们在runAsync中调用resolve时传的的参数。运行这段代码,会在2秒后输出“执行完成”,紧接着输出 “123” 。ui
这个时候你可能已经明白了,原来then
方法和咱们平时写的回调函数是一个道理,那咱们直接写回调函数就好了啊,为何还要写Promise呢。spa
确实在一些简单的场景下,回调函数已经够用,可是在如今前端的大环境和大发展的状态下,常常会出现回调地狱的状况,你可能须要在回调函数中,再继续回调函数,这样下去就会很恐怖了。Promise就给咱们带来了更好的解决办法。code
Promise的优点在于,能够在then方法中继续写Promise对象并返回,而后继续调用then来进行回调操做。对象
看下面一个例子,多层回调时是怎么使用的:
function runAsync1() {
var p = new Promise(function(resolve, reject) {
setTimeout(function(){
console.log('执行完成1');
resolve(1);
}, 2000)
})
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;
}
runAsync1().then(function(data) {
console.log(data);
return runAsync2();
}).then(function(data) {
console.log(data);
return runAsync3();
}).then(function(data) {
console.log(data);
return '直接返回数据'
}).then(function(data) {
console.log(data);
})
复制代码
在链式操做中,当一个Promise结束后,能够继续返回一个新的Promise,在下一个then
方法中继续接收其返回的resolve
。
在then方法中,你也能够直接return数据而不是Promise对象,在后面的then中就能够接收到数据了,看上面例子的最后一个。
说完resolve
,就不得不说reject
,它们都是Promise自身的方法,简单来讲,reject方法返回的是错误信息,将Promise的状态置为rejected
,上面已经说过。
咱们下面来看看具体的实现:
function getNumber() {
var p = new Promise(function(resolve, reject) {
setTimeout(function(){
var num = Math.ceil(Math.random()*10);
if(num<5) {
resolve(num)
} else {
reject('数字太大了')
}
}, 2000)
});
return p;
}
getNumber()
.then(
function(data) {
console.log('resolve')
console.log(data);
},
function(reason) {
console.log('reject')
console.log(reason);
}
)
复制代码
咱们建立一个随机1-10的数,判断大小,返回不一样的resolve和reject。
首先咱们能够在then方法中第二个参数来接收reject返回值。若是是大于5咱们就会打印出数字太大了
。
可是不少人以前都有接触过Promise,知道还有一个catch
的链式操做方法。它也能够用来接收reject
返回的信息。来看下面的代码:
getNumber()
.then(function(data) {
console.log('resolve');
console.log(data);
})
.catch(function(reason) {
console.log('reject');
console.log(reason);
})
复制代码
若是数字大于5就会打印 reject 6
。
若是你在then
中出现了错误,也不会中断程序的运行,会在catch
中打印出错误信息:
getNumber()
.then(function(data) {
console.log('resolve');
console.log(data);
console.log(somedata);
})
.catch(function(reason) {
console.log('reject');
console.log(reason); // ReferenceError: somedata is not defined
})
复制代码