异步编程——promise

测试账号 2021-01-09 09:33 857阅读 0赞

异步编程——promise

定义

Promise是异步编程的一个解决方案,相比传统的解决方法——回调函数,使用Promise更为合理和强大,避免了回调函数之间的层层嵌套,也使得代码结构更为清晰,便于维护。Promise 是一个对象,从他可以获取异步操作的消息,他也是一个容器,里面包含着事件结束之后要进行的操作。

特点

Promise对象有两个特点:

  • 对象的状态不收外界干扰。Promise对象有三种状态:pending(进行中)、resolved(已完成)、rejected(已失败),具体处于哪一种状态是由异步操作的结果来决定的,其他的任何操作都无法改变这个状态。
  • 一旦状态改变了,就不会再有其他的改变了,任何时候都能得到这个结果。Promise对象状态的改变有两种:1>.pending状态到resolved状态;2>.pending状态到rejected状态;

用法

Promise是一个构造函数,生成一个实例。

  1. var promise = new Promise(function (resolve, reject) {
  2. if (异步成功) {
  3. resolve(val);
  4. } else {
  5. reject(val);
  6. }
  7. });
  8. promise.then(function (val) {
  9. 成功后执行的函数
  10. }, function (error) {
  11. 失败后执行的函数
  12. });

Promise构造函数接收一个函数作为参数,这个函数有两个参数resolve、reject,这两个参数也是两个函数,有javascript引擎提供,不需要自己实现。其中,resolve函数的作用是将Promise对象的状态由”进行中”变为”已完成”,在异步操作成功的时候调用,并将异步操作的结果以参数的形式传出,就是上例中的val。reject函数的作用是将Promise对象的状态由”进行中”变为”已失败”,在异步操作失败的时候调用,并将操作失败的错误已参数的形式传出。

Promise的实例可以调用then方法,then方法有两个函数作为参数,第一个函数是Promise对象状态变为resoloved时执行的函数,第二个函数是Promise对象状态变为rejected时执行的函数,第二个参数是可选的。

一个典型的例子:异步读取文件

  1. function readFileFn(filename) {
  2. return new Promise(function (resolve, reject) {
  3. fs.readfile(filename, function (err, data) {
  4. if (err) {
  5. reject(err);
  6. } else {
  7. resolve(data);
  8. }
  9. });
  10. });
  11. }
  12. readFileFn("./test.txt").then(function (data) {
  13. console.log(data.toString());
  14. //其他操作...
  15. }, function (err) {
  16. console.log(err);
  17. });

then方法可以采用链式的写法,即:

promise.then(...).then(...).then(..)

具体的例子:

  1. var promise = new Promse(function (resolve, reject) {
  2. resolve(1);
  3. //将Promise对象的状态改为resolved,并传递参数1
  4. });
  5. promise.then(function (val) {
  6. console.log(val);
  7. // 1
  8. return val * 3;
  9. }).then(function (val) {
  10. console.log(val);
  11. // 3
  12. return val * 3;
  13. }).then(function (val) {
  14. console.log(val);
  15. // 9
  16. });

Promise对象的一些其他方法

  • Promise.prototype.catch:用于指定发生错误时的回调函数,通常的用法是在then方法里省略第二个参数,然后在链式调用的尾部使用catch方法来捕获异步操作或者then方法中的错误;
  1. readFileFn("./test.txt").then(function (data) {
  2. console.log(data.toString());
  3. //其他操作...
  4. }).catch(function (err) {
  5. console.log(err);
  6. })
  7. // 另一种用法
  8. var promise = new Promise(function (resolve, reject) {
  9. reject(new Error("test"));
  10. });
  11. promise.then(function (val) {
  12. // ...
  13. }).catch(function (err) {
  14. console.log(err);
  15. // ..
  16. });
  • Promise.all():次方法用于将多个Promise实例包装成一个新的Promise实例。Promise.all()方法接收一个数组作为参数:

var p = Promise.all([a,b,c]); //a,b,c都是Promise的实例

p最终的状态由a,b,c三者决定:

1>.当a,b,c的状态都是resolved时,p的状态才是resolved,此时a,b,c的返回值组成一个数组,传给p的回调函数。

2>.只要 a,b,c中有一个状态时reject,p的状态就是reject,此时一个reject的实例的返回值会传递给p的回调函数。

  1. var promises = [1, 2, 3, 4].map(function (id) {
  2. return readFileFn("./test" + id + ".txt");
  3. //readFileFn()是上面声明过的函数
  4. });
  5. Promise.all(promises).then(function (val) {
  6. // ...
  7. }).catch(function (err) {
  8. // ...
  9. });
  • Promise.race():同样是将多个Promise实例包装成一个新的Promise实例,与Promise.all()方法类似;
  • Promise.resolve():将一个非Promise对象转换为一个Promise对象,

var promise = Promise.resolve($.ajax("./test.txt"));

Promise.resolve()有四种类型的参数:

1>.Promise实例,那么函数不会对参数做任何修改,原样返回;

2>.普通对象,如同上例,会转换成一个promise对象返回;

3>.非对象,即普通的变量,比如”hello”、2 等等,此时会返回一个新的Promise实例,状态为resolved(),”hello”会以参数的形式传给then的第一个方法;

  1. var p = Promise.resolve("hello"); p.then(function(val){ //此函数会立即执行 console.log(val); //hello });

4>.不带参数,会直接返回一个Resolved状态的Promise对象。

  • Promise.reject():返回一个状态为rejected的实例,参数类似于Promise.resolve()方法的第三种参数。
  • done():Promise内部的错误不会冒泡到全局,所以,如果回调链的最后一个出现错误,就无法被捕获,所以有了done()方法,位于回调链的最尾端,用于捕获错误。

promise.then(function(){}).then(function(){}).catch(function(){}).done();

  • finally():指定不管Promise最后的状态如何都会执行的操作,他与done()的区别是可以接受一个普通的回调函数作为参数,且该函数一定会执行。

发表评论

表情:
评论列表 (有 0 条评论,857人围观)

还没有评论,来说两句吧...

相关阅读

    相关 异步编程——promise

    异步编程——promise 定义 Promise是异步编程的一个解决方案,相比传统的解决方法——回调函数,使用Promise更为合理和强大,避免了回调函数之间的层层嵌套,...