目录标题
promise简介promise容器中的执行顺序resolve函数和reject函数中传递的参数如果resolve或reject中的参数是一个正常的值如果resolve或reject中的参数是promise实例对象
Promise.prototype.then()成功时的回调 和 失败时的回调函数 中的return返回值如果返回值为一个普通参数如果返回值为一个新的promise实例
成功时的回调 和 失败时的回调函数 中抛出异常Promise.prototype.catch()参考文章
promise简介
为了解决回调地狱嵌套,在EcmaScript6中新增了一个API:Promise。Promise是一个构造函数。Promise是一个容器,Promise本身不是异步的,但是容器内部往往存放一个异步操作。Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve和reject两个形参接收的是函数,接受的函数由 JavaScript 引擎提供,不用自己部署。通过new Promise构造器创建的promise对象是有状态的,状态可能是pending(进行中),resolved(已完成,也称为fullfilled),rejected(已失败)中的一种。新创建的promise对象的状态是pending,后续可以变为resolved或rejected,状态一旦改为resolved或rejected,就不会再变了。resolve函数调用后会将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数调用后将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
例一:
const promise
= new Promise(function(resolve
, reject
) {
if (){
resolve(value
);
console
.log(1)
} else {
reject(error
);
}
});
Promise实例生成以后,可以用then方法指定两个回调函数。then方法中的第一个参数,是promise对象的状态由pending变为resolved后会调用的回调函数;then方法中的第二个参数,是promise对象的状态由pending变为rejected后调用的回调函数;这两个回调函数中,rejectedCallback可选的,不一定要提供。例一中,如果异步操作成功,就会调用resolve(value),调用resolve(value),当前promise的状态由进行中变为成功,随即调用then方法中的第一个回调函数参数。我们在例一中调用resolve(value)的时候其实就可以看作是在调用then方法里传的第一个回调函数。then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行( 也就是说resolve()后面如果还有其他同步语句(如上面例子中的console.log(1) ),会先执行完这些同步语句, 然后在执行then方法中的回调函数)。
promise
.then(resolvedCallback
, rejectedCallback
);
promise
.then(function(value
) {
}, function(error
) {
});
例二:
下面的代码中,首先利用Promise构造器创建了一个promise对象,并且调用了then方法指定了该promise对象的状态由pending变为resolved后会调用的回调函数。promise里的异步操作是一个定时操作,当计时到了后,调用了resolve()函数(也就是调用了我们在then方法中写的第一个回调函数),该函数调用后,promise对象的状态由pending变为resolved。
new Promise((resolve
, reject
) => {
setTimeout(function () {
resolve() ;
}, 1000)
}).then((data
) => {
alert('成功的回调');
})
promise容器中的执行顺序
new Promise((resolve
, reject
) => {
setTimeout(function () {
console
.log('时间到了')
resolve('11')
console
.log('22')
}, 1000)
console
.log('33')
}).then((data
) => {
console
.log(data
)
})
console
.log('hhh')
promise本身不是异步的,只是内部包含了异步代码。首先启动定时器(但是不会执行定时器内部的回调函数)因为setTimeout是一个异步代码,不会影响后续代码的继续执行,所以随即执行 console.log(‘33’)new Promise部分就执行完了,然后按顺序执行 console.log(‘hhh’)当定时到了后,会执行定时器中的回调函数,依次执行 console.log(‘时间到了’) resolve(‘11’) (实际上可以看作执行then方法传过去的回调函数) console.log(‘22’)按照上面的说法应该先打印11,在打印22呀?这是为什么呢?这就是前面提到的 then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行, 也就是说console.log(22)会先打印。
resolve函数和reject函数中传递的参数
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例。
如果resolve或reject中的参数是一个正常的值
例三:
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve(1);
}, 1000);
})
p1
.then(function (data
) {
console
.log("data", data
)
}, function (err
) {
console
.log("err", err
)
})
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
reject(1);
}, 1000);
})
p1
.then(function (data
) {
console
.log("data", data
)
}, function (err
) {
console
.log("err", err
)
})
如果resolve或reject中的参数是promise实例对象
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 3000);
})
var p2
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve(p1
);
}, 1000);
})
p2
.then(function (data
) {
console
.log('resolve执行啦')
console
.log(data
)
}, function (err
) {
console
.log(err
)
})
上面代码中,p1和p2都是 Promise 的实例,但是p2的resolve方法将p1作为参数。注意,这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。
Promise.prototype.then()
then方法会返回一个新的Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法。采用链式的then,可以指定一组按照次序调用的回调函数。
成功时的回调 和 失败时的回调函数 中的return返回值
第一个回调函数完成以后,会将返回结果作为参数,传入下一级的回调函数。返回结果可能是一个参数或者一个新的promise实例(即有异步操作),这时候一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。如果then方法中的回调函数(不管是成功的回调还是失败的回调)返回了一个参数(return xxx),那么这个then方法返回的新的promise的状态会变成fulfilled(同时成功的回调函数也会被调用)。
如果返回值为一个普通参数
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
var p2
= p1
.then(function (data
) {
console
.log("data", data
);
return 'hello p2';
}, function (err
) {
console
.log("err", err
);
return 'hello p2 nihao';
});
var p3
= p2
.then(function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
写成链式调用的形式:
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
p1
.then(function (data
) {
console
.log("data", data
);
return 'hello p2';
}, function (err
) {
console
.log("err", err
)
return 'hello p2 nihao';
})
.then(function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
reject('1');
}, 1000);
})
var p2
= p1
.then(function (data
) {
console
.log("data", data
);
return 'hello p2';
}, function (err
) {
console
.log("err", err
)
return 'hello p2 nihao';
});
p2
.then(function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
从上面的例子可以总结出:如果then方法中返回一个参数(return xxx),那么这个then方法返回的新的promise的状态会变成fulfilled。
如果返回值为一个新的promise实例
var time1
, time2
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
var p2
;
p1
.then (function (data
) {
time1
= Date
.now()
console
.log("data", data
);
p2
=
new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('2');
}, 3000);
});
return p2
;
}, function (err
) {
console
.log("err", err
)
})
.then (function (data
) {
time2
= Date
.now()
console
.log(time2
-time1
)
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
写成链式的
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
p1
.then (function (data
) {
console
.log("data", data
);
return new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('2');
}, 3000);
});
}, function (err
) {
console
.log("err", err
)
})
.then (function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
成功时的回调 和 失败时的回调函数 中抛出异常
如果then中抛出异常,那么这个then返回的新的promise实例的状态会被置为rejected
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
var p2
= p1
.then (function (data
) {
console
.log("data", data
);
throw new Error('test1');
}, function (err
) {
console
.log("err", err
);
throw new Error('test2');
})
p2
.then (function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
reject('1');
}, 1000);
})
var p2
= p1
.then (function (data
) {
console
.log("data", data
);
throw new Error('test1');
}, function (err
) {
console
.log("err", err
);
throw new Error('test2');
})
p2
.then (function (data
) {
console
.log("data", data
);
}, function (err
) {
console
.log("err", err
);
})
Promise.prototype.catch()
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
var p2
= p1
.then (function (data
) {
console
.log("data", data
);
throw new Error('test1');
}, function (err
) {
console
.log("err", err
);
throw new Error('test2');
})
p2
.catch (function (err
) {
console
.log("err", err
);
})
var p1
= new Promise(function (resolve
, reject
) {
setTimeout(function () {
resolve('1');
}, 1000);
})
p1
.then (function (data
) {
console
.log("data", data
);
return new Promise(function (resolve
, reject
) {
setTimeout(function () {
reject('2');
}, 3000);
});
}, function (err
) {
console
.log("err", err
)
})
.catch (function (err
) {
console
.log("err", err
);
})
参考文章
https://es6.ruanyifeng.com/#docs/promise https://segmentfault.com/a/1190000011652907