美文网首页
RN异步编程系列:ES6中Promise的用法

RN异步编程系列:ES6中Promise的用法

作者: sy随缘 | 来源:发表于2018-09-12 15:32 被阅读0次

参考链接:
学习RxJS: 导入
http://www.moye.me/2016/05/31/learning_rxjs_part_one_preliminary/

RxJS中文文档
https://cn.rx.js.org

Lodash中文文档
https://www.lodashjs.com

阮一峰的ES6入门:Promise 对象
http://es6.ruanyifeng.com/#docs/promise

ES6关于Promise的用法
https://segmentfault.com/a/1190000011652907

ES6 Promise 用法(我见过最简洁优秀的文章)
https://blog.csdn.net/shan1991fei/article/details/78966297


引子

新手们在异步编程里跌倒时,永远会有这么一个经典问题:
怎么在一次异步调用里return一个结果啊?

老司机说要用【回调函数】,然后有条件判断的嵌套回调(回调地狱)问题来了;

老司机推荐用【事件】,然后异步流程里有顺序依赖;

老司机推荐用【Promise】,然后有顺序依赖的流程里,居然还想订阅事件;

老司机建议试试【协程】,谁知对方想要合并两个异步调用;

……

以上,是异步编程里要面对的一些难题,也是【ReactiveX API】 所致力解决的


一、Promise的用法

  1. Promise 的含义
  2. 基本用法
  3. Promise.prototype.then()
  4. Promise.prototype.catch()
  5. Promise.prototype.finally()
  6. Promise.all()
  7. Promise.race()
  8. Promise.resolve()
  9. Promise.reject()
  10. 应用
  11. Promise.try()

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise
简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:
pending变为fulfilled
pending变为rejected
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。
1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
3、当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署Promise更好的选择。


如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加一层嵌套下去。

为了解决这个问题,ES6提出了Promise的实现。

含义
Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。
简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。


例子

var promise1 = new Promise(function(resolve, reject) {
  // 2秒后置为接收状态
  setTimeout(function() {
    resolve('success');
  }, 2000);
});

promise1.then(function(data) {
  console.log(data); // success
}, function(err) {
  console.log(err); // 不执行
}).then(function(data) {
  // 上一步的then()方法没有返回值
  console.log('链式调用:' + data); // 链式调用:undefined 
}).then(function(data) {
  // ....
});

在这里我们主要关注promise1.then()方法调用后返回的Promise对象的状态,是pending还是fulfilled,或者是rejected?

返回的这个Promise对象的状态主要是根据promise1.then()方法返回的值,大致分为以下几种情况:
如果then()方法中返回了一个参数值,那么返回的Promise将会变成接收状态。
如果then()方法中抛出了一个异常,那么返回的Promise将会变成拒绝状态。
如果then()方法调用resolve()方法,那么返回的Promise将会变成接收状态。
如果then()方法调用reject()方法,那么返回的Promise将会变成拒绝状态。
如果then()方法返回了一个未知状态(pending)的Promise新实例,那么返回的新Promise就是未知状态。
如果then()方法没有明确指定的resolve(data)/reject(data)/return data时,那么返回的新Promise就是接收状态,可以一层一层地往下传递。

转换实例如下:

var promise2 = new Promise(function(resolve, reject) {
  // 2秒后置为接收状态
  setTimeout(function() {
    resolve('success');
  }, 2000);
});

promise2
  .then(function(data) {
    // 上一个then()调用了resolve,置为fulfilled态
    console.log('第一个then');
    console.log(data);
    return '2';
  })
  .then(function(data) {
    // 此时这里的状态也是fulfilled, 因为上一步返回了2
    console.log('第二个then');
    console.log(data);  // 2

    return new Promise(function(resolve, reject) {
      reject('把状态置为rejected error'); // 返回一个rejected的Promise实例
    });
  }, function(err) {
    // error
  })
  .then(function(data) {
    /* 这里不运行 */
    console.log('第三个then');
    console.log(data);
    // ....
  }, function(err) {
    // error回调
    // 此时这里的状态也是fulfilled, 因为上一步使用了reject()来返回值
    console.log('出错:' + err); // 出错:把状态置为rejected error
  })
  .then(function(data) {
    // 没有明确指定返回值,默认返回fulfilled
    console.log('这里是fulfilled态');
});

下面代码中,booksPromise和userPromise是两个异步操作,只有等到它们的结果都返回了,才会触发pickTopRecommentations这个回调函数。

const databasePromise = connectDatabase();

const booksPromise = databasePromise
  .then(findAllBooks);

const userPromise = databasePromise
  .then(getCurrentUser);

Promise.all([
  booksPromise,
  userPromise
])
.then(([books, user]) => pickTopRecommentations(books, user));


下面代码中,如果 5 秒之内fetch方法无法返回结果,变量p的状态就会变为rejected,从而触发catch方法指定的回调函数。

const p = Promise.race([
  fetch('/resource-that-may-take-a-while'),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error('request timeout')), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

相关文章

  • Promise

    Promise Promise 是异步编程的一种解决方案,es6中统一器用法,原生提供了promise对象 Pro...

  • RN异步编程系列:ES6中Promise的用法

    参考链接:学习RxJS: 导入http://www.moye.me/2016/05/31/learning_rxj...

  • 【ECMAScript6】 Promise

    Promise 是什么 Promise 是 ES6 为 JavaScript 异步编程定义的全新 api 。为异步...

  • es6Promise学习笔记

    Promise 是异步编程的一种解决方案,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。有...

  • Promise

    es6中有个特别的对象Promise,今天我们就来学习它,了解它。 Promise含义 Promise 是异步编程...

  • ES6 Promise 异步编程方案

    为什么使用 Promise ? Promise 是 ES6 提出的异步编程方案 ! ES6 之前,如果我们都是通过...

  • ES6/7异步编程方法总结

    ES6提供了异步编程的几个新特性:本篇主要参考阮一峰大神的ES6文章。 Promise 1.基本用法: Promi...

  • [ES6] Promise

    Promise Promise是ES6提出解决异步编程的方案,相比于传统的回调函数,Promise更符合人们的编程...

  • React学习笔记(9)Promise

    阮一峰ES6 Promise Promise定义 Promise 是异步编程的一种解决方案,所谓Promise,简...

  • ES6-Promise

    参考链接: 1.阮一峰Promise解读 2.Promise用法讲解 Promise含义 Promise是异步编程...

网友评论

      本文标题:RN异步编程系列:ES6中Promise的用法

      本文链接:https://www.haomeiwen.com/subject/aygvgftx.html