关于JavaScript中es6-promise的应用
应用promise背景
由于我们公司需要开发微信小程序,并且小程序API大部分都是异步的API,不采用promise的话,将会出现代码一个嵌套一个的情况。如下所示:
A(){
B(){
C(){
}
}
}
这种代码结构非常不利于阅读,为此我网上了解了下,发现promise可以让异步调用 进行同步顺序向下执行。
es6与Promise的关系
- ES6, 全称 ECMAScript 6.0 ,是 JaveScript 的下一个版本标准,2015.06 发版。
- promise是es6中的一个组成部分。
了解主流浏览器对promise的兼容
对于前端需要了解的就是浏览器支不支持promise了,这样我们才能确定到底要不要采用promise。
经过查阅,微信小程序支持es6的promise,点此查看。
记录一些自己对promise的理解
- 网上已经有很多的大神介绍promise了,阮一峰 promise入门,下面我就简单记录下简单入门和一些注意点。
- 首先下载 es6-promise,放进微信小程序项目中。
- 基本知识:
(1) promiseg概念
是异步编程的一种解决方案。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
(2) Promise 的状态和特点
Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。
const p1 = new Promise(function(resolve,reject){
resolve('success1');
resolve('success2');
});
const p2 = new Promise(function(){
resolve('success3');
reject('reject');
});
p1.then(function(value){
console.log(value); // 输出 success1
});
p2.then(function(value){
console.log(value); // 输出 success3
});
(3) Promise 的 then 方法
then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。
通过 .then 形式添加的回调函数,不论什么时候,都会被调用。
const p = new Promise(function(resolve,reject){
resolve('do_success');
//reject('do_fail');
});
p.then( success => {
console.log(success);
}, fail => {
console.log(fail);
}
);
console.log('first');
// first
// do_success
(4) promise的链式执行顺序
网上介绍的promise 的then方法为 同步还是异步函数的执行顺序,讲解的并不是很齐全,这边我整理了一下。
(1)
const p = new Promise(function(resolve,reject){
setTimeout(
console.log("first"), 3000
resolve(1); //必须加在异步执行结束之后
);
}).then(function(value){ // 第一个then // 1
console.log(value); //第一个then里面的函数执行,必定是在p执行成功后才会执行。如果p执行失败(改为reject)会直接跳到catch
return value * 2;
}).then( value => { // 第二个then // 2
console.log(value);
}).then(function(value){ // 第三个then // undefined
console.log(value);
return Promise.resolve('resolve');
}).then(function(value){ // 第四个then // resolve
console.log(value);
return Promise.reject('reject');
}).then(function(value){ // 第五个then //不执行
console.log('resolve:' + value);
}).catch(function(value){ // catch // catch: reject
console.log('catch:' + value);
})
(2) then 里面放 异步函数并不能让该异步函数顺序执行下来。
异步函数里面经过promise封装,把resolve或reject 放在异步执行完后面,这样才能顺序执行下来。
const p = new Promise(function(resolve,reject){
setTimeout(function() {
console.log('s1');
resolve(1); //需要放setTimeout里面这样才能顺序执行到 then
}, 3000);
}).then(function(value){
setTimeout(function() {
console.log('s2');
}, 1000); //s2并不会比s3早输出,需要经过封装
}).then( value => {
setTimeout(function() {
console.log('s3');
}, 500);
})
执行结果
> "s1"
> "s3"
> "s2"
调用模型:
//引入Promise js文件
const Promise = require('../../es6/es6-promise.min.js')
(1) 创建带有Promise的函数
function ptest(){
return new Promise(function (resolve, reject) {
//执行结束
resolve(res) //给调用ptest的链式向下执行
reject(res) //给调用ptest的链式直接跳到 catch 中
}
}
(2) 调用带有Promise的函数,用于同步执行函数
ptest
.then(function(res){
return A()
})
.then(function(res){
console.log(res) //A函数前必须加return, 这里才能打印出A的返回结果
return B()
})
.catch(function(res){
//执行ptest、A、B过程中 带有reject(或者执行失败),就跳到这里来
})
.finally(function(res){
//最后都会执行这个
})
//类似try catch finally 结构
(3) 调用不带Promise的函数,用于同步执行函数
var promise1 = new Promise(function(resolve, reject) {
// setTimeout为异步函数, 这里使用Promise封装
console.log("test0");
setTimeout(function() {
resolve('test1');
}, 300);
});
promise1.then(function(res) {
console.log(res);
return "test2"
})
.then(function(res) {
console.log(res);
})
.catch(function(res) {
console.log(res);
})
console.log("test3");
·······················································
//执行结果:
> "test0"
> "test3" //请注意test3,比then先执行,
> "test1"
> "test2" (为了让test1比test2先输出,必须使用promise封装)
·······················································
(4) 调用不带Promise的函数, !!!不可用
const p = Promise.resolve();
p.then(function () {
setTimeout(function() {
console.log('1');
}, 2000);
})
.then(function () {
console.log('2');
})
·······················································
//执行结果:
> "2"
> "1"
请注意,这种方法并不能让异步的顺序执行。
·······················································
异步函数顺序执行
// 异步函数a
var a = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("log-a")
setTimeout(function () {
console.log("log-aa")
resolve('a')
}, 2000)
}, 2000)
})
}
// 异步函数b
var b = function (data) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("log-b")
resolve(data + 'b')
}, 1500)
})
}
// 异步函数c
var c = function (data) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log("log-c")
resolve(data + 'c')
}, 500)
})
}
a()
.then(function (data) {
return b(data)
})
.then(function (data) {
return c(data)
})
.then(function (data) {
console.log(data)// abc
})
嵌套关系的promise,执行顺序
从下面的例子可以看出,promise1 的链对应自己的catch
promise2 的链对应自己的catch。
var promise1 = new Promise(function(resolve, reject) {
resolve('test1');
});
var promise2 = new Promise(function(resolve, reject) {
reject('test1');
});
promise1.then(function(res) {
return "test2"
})
.then(function(res) {
promise2.then(res =>{
console.log("promise2 then");
}).catch(res =>{
console.log("promise2 catch");
})
})
.catch(function(res) {
console.log("final catch");
})
执行结果:
> "promise2 catch"
链式调用中的then怎么中断
A.then(
if( a == 1)
return "test" //向下执行
else
{
throw err 停止,不跳转catch
return Promise.reject('reject'); //停止,跳转catch
}
)
.then(
)
.then(
)
.then(
)
.catch(
)
阮一峰 promise入门
mozilla promise教学
ES6 Promise 对象(推荐初学者看这个)
setTimeout async promise执行顺序总结
构建Promise队列实现异步函数顺序执行