博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6中的Promise使用方法与总结
阅读量:6284 次
发布时间:2019-06-22

本文共 6818 字,大约阅读时间需要 22 分钟。

在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对象,并以该值resolvelet 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);});

  

 

转载于:https://www.cnblogs.com/jkko123/p/10217356.html

你可能感兴趣的文章
Sphinx 配置文件说明
查看>>
数据结构实践——顺序表应用
查看>>
python2.7 之centos7 安装 pip, Scrapy
查看>>
机智云开源框架初始化顺序
查看>>
Spark修炼之道(进阶篇)——Spark入门到精通:第五节 Spark编程模型(二)
查看>>
一线架构师实践指南:云时代下双活零切换的七大关键点
查看>>
ART世界探险(19) - 优化编译器的编译流程
查看>>
玩转Edas应用部署
查看>>
music-音符与常用记号
查看>>
sql操作命令
查看>>
zip 数据压缩
查看>>
Python爬虫学习系列教程
查看>>
【数据库优化专题】MySQL视图优化(二)
查看>>
【转载】每个程序员都应该学习使用Python或Ruby
查看>>
PHP高级编程之守护进程,实现优雅重启
查看>>
PHP字符编码转换类3
查看>>
rsync同步服务配置手记
查看>>
http缓存知识
查看>>
Go 时间交并集小工具
查看>>
iOS 多线程总结
查看>>