ES6中的Promise使用方法与总结
在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的。
但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回调函数里,这样一层嵌一层,最终形成回调地狱。
$.get('/login.php', function (login) {
$.get('/user.php', function (user) {
$.get('/info.php', function (info) {
//代码就这样一层嵌一层,不够直观,维护也麻烦
});
});
});
为了解决这种问题,ES6中就提供了Promise方法来解决这种问题。
Promise是一个构造函数,通过它,我们可以创建一个Promise实例对象。
let p = new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('OK');
resolve('OK');
}, 1000);
});
Promise构造函数接受一个函数作为参数,这个函数有两个参数,resolve和reject。
resolve函数是将Promise的状态设置为fulfilled(完成),reject函数是将Promise的状态设置为rejected(失败)。
上述代码,我们并没有进行任何调用,当运行时,间隔1秒后输出了'OK'。所以这里需要注意,我们通常使用Promise时,需要在外层再包裹一层函数。
let p = function () {
return new Promise(function (resolve, reject) {
setTimeout(() => {
console.log('OK');
resolve('OK');
}, 1000);
});
};
p();
上面的代码p();返回的是一个Promise实例对象,Promise对象上有 then() , catch() , finally() 方法。
then方法有两个参数,onFulfilled和onRejected,都是函数。
onFulfilled用于接收resolve方法传递过来的数据,onRejected用于接收reject方法传递过来的数据。
let p = function () {
return new Promise(function (resolve, reject) {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('OK');
} else {
reject('ERR');
}
}, 1000);
});
};
p().then(function (data) {
console.log('fulfilled', data);
}, function (err) {
console.log('rejected', err);
});
then()方法总是会返回一个Promise实例,这样我们就可以一直调用then()。
在then方法中,你既可以return 一个具体的值 ,还可以return 一个Promise对象。
如果直接return的是一个数据,那then方法会返回一个新Promise对象,并以该数据进行resolve。
let p = function () {
return new Promise(function (resolve, reject) {
resolve(1);
});
};
p().then(function (data) {
console.log(`第 ${data} 次调用`);
//注意这里直接返回的值
//then会创建一个新的Promise对象,并且以返回的值进行resolve
//那么该值会被下面的then方法的onFulfilled回调拿到
return ++data;
}).then(function (data) {
console.log(`第 ${data} 次调用`);
return ++data;
}).then(function (data) {
console.log(`第 ${data} 次调用`);
return ++data;
});
如果返回的是一个Promise对象,请看下面代码。
let p = function () {
return new Promise(function (resolve, reject) {
resolve(1);
});
};
p().then(function (data) {
console.log(`第 ${data} 次调用`);
return new Promise(function (resolve, reject) {
resolve(++data);
});
}).then(function (data) {
console.log(`第 ${data} 次调用`);
return new Promise(function (resolve, reject) {
resolve(++data);
});
}).then(function (data) {
console.log(`第 ${data} 次调用`);
return new Promise(function (resolve, reject) {
resolve(++data);
});
});
其实效果与直接返回值的是一样的。
即然then()可以进行链式操作,那我们最早之前的回调地狱写法,就可以通过它进行改进了。
function login() {
return new Promise(function (resolve, reject) {
$.get('/login.php', function (result) {
resolve(result);
});
});
}
function user(data) {
return new Promise(function (resolve, reject) {
$.get('/user.php', function (result) {
resolve(result);
});
});
}
function info(data) {
return new Promise(function (resolve, reject) {
$.get('/info.php', function (result) {
resolve(result);
});
});
}
login().then(function (data) {
console.log('处理login');
//把login异步处理获取的数据,传入到下一个处理中。
return user(data);
}).then(function (data) {
console.log('处理user');
//把user异步处理获取的数据,传入到下一个处理中。
return info(data);
}).then(function (data) {
console.log('处理info');
});
这样修改后,回调地狱层层嵌套的结构就变的清晰多了。上述代码是伪代码。
Promise对象还有一个catch方法,用于捕获错误,该方法与 then(null, onRejected) 等同,是一个语法糖。
let p = function () {
return new Promise(function (resolve, reject) {
resolve('开始');
});
};
p().then(function (data) {
console.log('1');
return new Promise(function (resolve, reject) {
reject('错误1');
});
}).then(function (data) {
console.log('2');
return new Promise(function (resolve, reject) {
reject('错误2');
});
}).then(function (data) {
console.log('3');
return new Promise(function (resolve, reject) {
reject('错误3');
});
}).catch(function (reason) {
console.log(reason);
});
注意,一旦操作中有错误发生,则会进入到catch中,后面的操作将不再执行。
Promise对象内部自带了try catch,当代码运行时错误,会自动以错误对象为值reject,并最终被catch捕获。
let p = function () {
return new Promise(function (resolve, reject) {
resolve('开始');
});
};
p().then(function (data) {
//注意这里打印了一个未定义的变量
console.log(a);
}).catch(function (reason) {
//这里会捕获到错误
console.log('rejected');
console.log(reason);
});
Promise还提供了,all(),race(),reject(),resolve()等在构造函数上的方法,调用这些方法并不需要实例化对象。
all()方法,可以让我们并行的执行异步操作,直到所有操作完成了,才执行回调。
function fn1() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn1');
}, 1000);
});
}
function fn2() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn2');
}, 2000);
});
}
function fn3() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn3');
}, 3000);
});
}
//all会等待所有操作完成,会把所有操作的结果放到一个数组中,传给then。
Promise.all([fn1(), fn2(), fn3()]).then(function (data) {
console.log(data);
});
race()方法是谁先处理完,就以谁为准,把最先处理完的结果传给then。
function fn1() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn1');
}, 1000);
});
}
function fn2() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn2');
}, 2000);
});
}
function fn3() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('fn3');
}, 3000);
});
}
//race是以谁先处理完,就以谁为准,fn1最先处理完,那fn1的结果会传给then
//注意这里fn2和fn3还是会执行,不过不会进入then了
Promise.race([fn1(), fn2(), fn3()]).then(function (data) {
console.log(data);
});
reject()方法,返回一个带有拒绝原因reason参数的Promise对象。
// Promise.reject('错误')
// 等同于
// new Promise(function(resolve, reject) {
// reject('错误');
// });
let p = Promise.reject('错误');
p.then(function (data) {
}).catch(function (reason) {
console.log(reason);
});
resolve()方法,根据传入的值返回一个Promise对象。
//如果传入的参数是普通值,则返回一个新Promise对象,并以该值resolve
let p1 = Promise.resolve('OK');
p1.then(function (data) {
console.log(data);
}); //如果传入的参数是一个Promise对象,则原封不动的返回该Promise对象
let obj = new Promise(function (resolve, reject) {
resolve('我是Promise对象');
});
let p2 = Promise.resolve(obj);
p2.then(function (data) {
console.log(data);
console.log(p2 === obj);
}); //如果传入的参数是一个thenable对象(带有then方法),
//会转换成Promise对象,并执行thenable对象的then方法
let then = {
then(resolve, reject) {
resolve('我是thenable对象');
}
}
let p3 = Promise.resolve(then);
p3.then(function (data) {
console.log(data);
}); //如果什么参数都不传入,则返回状态为resolved的Promise对象
let p4 = Promise.resolve();
p4.then(function (data) {
console.log(data);
}).catch(function (reason) {
console.log(reason);
});
ES6中的Promise使用方法与总结的更多相关文章
- es6中的promise对象
Promise是异步里面的一种解决方案,解决了回调嵌套的问题,es6将其进行了语言标准,同意了用法,提供了`promise`对象, promise对象有三种状态:pending(进行中) .Resol ...
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...
- ES6中的Promise用法
Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交 ...
- es6中的Promise学习
关于Promise Promise实例一旦被创建就会被执行 Promise过程分为两个分支:pending=>resolved和pending=>rejected Promise状态改变后 ...
- ES6中的Promise详解
Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...
- 深入解析ES6中的promise
作者 | Jeskson来源 | 达达前端小酒馆 什么是Promise Promise对象是用于表示一个异步操作的最终状态(完成或失败)以及其返回的值. 什么是同步,异步 同步任务会阻塞程序的执行,如 ...
- [转]JS - Promise使用详解2(ES6中的Promise)
原文地址:https://www.hangge.com/blog/cache/detail_1638.html 2015年6月, ES2015(即 ECMAScript 6.ES6) 正式发布.其中 ...
- ES6中的Promise和Generator详解
目录 简介 Promise 什么是Promise Promise的特点 Promise的优点 Promise的缺点 Promise的用法 Promise的执行顺序 Promise.prototype. ...
- ES6中的promise
Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示.简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作. 它的一般表示形 ...
随机推荐
- replace()方法解析
search(),match(),用于查找指定字符串返回首次出现的索引值与指定的字符串.这篇我们讲找到指定字符串之后将其替换掉.直接贴: var str="Visit Microsoft!& ...
- 10. Lambda表达式.md
为了简化匿名内部类的代码,具体定义: 例如将9.内部类中的匿名内部类例子: 原来代码: //Main.java public class Main { public static void main( ...
- 19.Observales
然后 ng serve看看能不能启动 OK
- django select_related()和反射结合
对于有外键关联的表,select_related()会自动进行多变关联; ret = models.UserInfo.objects.all().select_related() print ret. ...
- 获取当前ip
测ip地址http://2018.ip138.com/ic.asphttps://www.ip.cn/
- 微信小程序-获取当前城市位置及再次授权地理位置
微信小程序-获取当前城市位置 1. 获取当前地理位置,可通过wx.getLocation接口,返回经纬度.速度等信息; 注意---它的默认工作机制: 首次进入页面,调用该api,返回用户授权结果,并保 ...
- JS----贪吃蛇游戏
在网上找到的几种例子 <!DOCTYPE html> <html > <head> <meta http-equiv="Content-Type&q ...
- Java NIO Files
Java NIO Files Files.exists() Files.createDirectory() Files.copy() Overwriting Existing Files Files. ...
- centos7下解压bz2文件
已有python2.7.5 已有yum 1.安装bzip2 yum install -y bzip2 2.改变压缩格式 bunzip2 dlib-19.13.tar.bz2 3.解压 tar -xf ...
- 一分钟了解Android横竖屏 mdpi hdpi xhdpi xxhdpi xxxhdpi (转)
转自:http://blog.csdn.net/a704755096/article/details/46342689 DPI:每英寸像素数 简单的屏幕分辨率计算方法: DisplayMetrics ...