Promise 学习

Promise

前言

之前写 JavaScript 异步处理时,一般都会用回调函数(callback)方式来处理异步的结果,例如:

function f (callback) { 
  setTimeout(() => {       // setTimeout 模拟耗时任务
    const result = 'f';
    callback(result)
  }, 1500) 
}

function f1 (res) {
  console.log(res + '->' + 'f1')
}

f(f1)  // f->f1

这样看起来很合理,也很好理解,但是,假如还有一个函数 f2,它需要根据 f1 的结果进行处理,如下:

// 修改f1
function f1 (callback) {
  const result = 'f1'
  return (res) => {
    callback(res + '->' + result)
  }
}
// 添加f2
function f2 (res) {
  console.log(res + '->' + 'f2')
}

f(f1(f2)) // f->f1->f2

会发现逻辑处理变得很复杂,如果还有其他函数继续调用,代码将变的很难维护。

什么是 Promise

Promise 是一个对象,代表一个异步操作,有三种状态:
* pending(进行中)
* fulfilled (已成功)
* rejected(已失败)

只有异步处理后的结果,才能决定当前出于哪种状态,其他操作无法改变这个状态,而且一旦状态改变,就不会再变,任何时候都能得到这个结果,这就是 promise 承诺的意思。
Promise 对象状态的改变就只有两种:从 pending 变为 fulfilled,从 pendingrejected,即 resolvereject 结果。

Promise 用法

Promise 是 ES6 的一个语言标准对象
一个实例:

const promise = new Promise (function(resolve, reject)) {
  // TODO

  if(/* 异步操作成功 */) {
    resolve(result)
  } else {
    reject(error)
  }
}

Promise 构造函数接受两个参数 resolve 和 reject,分别是在异步操作成功和失败的时候调用,然后作为参数传递出去。

如何把结果传递出去,使用 Promise的原型方法 then 或者 catch。

Promise.prototype.then

当 Promise 的状态发生改变时(resolve/reject),then 方法绑定的处理方法就会被调用。 then 方法包含两个参数,第一个参数绑定 resolve 状态的方法,第二个参数绑定 reject 状态的方法。

// 接上面的代码
promise.then(function (result) {
  console.log(result)
}, function (error) {
  console.log(error)
})

then 方法返回的是一个 Promise 对象,所以可以进行链式调用,如promise.then(//).then(//),第二个 then 已第一个 then 的结果作为参数。这个链式操作是 Promise 最大的作用。

利用 Promise 解决之前的回调问题:

function f() {
  const promise = new Promise((resolve, reject) => {
    setTimeout(function () { // setTimeout 模拟耗时任务
      const result = 'f';
      resolve(result);
    }, 1500)
  })

  return promise;
}

function f1 (res) {
  return (res + '->' + 'f1')
}

function f2 (res) {
  console.log(res + '->' + 'f2')
}

f().then(f1).then(f2) // f->f1->f2

这样代码变得很好理解和维护了。

Promise.prototype.catch

catch 和 then 一样,只是它的参数只有一个,处理 reject 状态的回调函数,返回的也是一个新 Promise对象。

promise.then(function (result) {
  console.log(result)
}).catch(function (error) {
  console.log(error)
})

其他方法

Promise.all()

参数是具有 iterator 接口,且成员都是 Promise 对象的数据结构,返回一个新的 Promise 对象。

let p = Promise.all([p1, p2, p3])

p 的状态由 p1、p2、p3 决定:
* 如果 p1、p2、p3 的状态都是 resolve,那么 p 才是 resolve
* 只要其中一个是 reject,那么p的结果就是 reject

注意一点,这三者是并行处理的,设计的时候三者完全不相关。

Promise.race()

赛跑模式,参数和返回值和 all 方法一样:

let p = Promise.race([p1, p2, p3])

不同的是,p1、p2、p3之中一个对象率先改变状态,p的状态就跟第一个改变状态的结果而改变。

Promise.resolve()

会生成一个 Promise 对象,且它的状态为 resolve

let p = Promise.resolve('resolve');
p.then(function (res){
  console.log(res) // 'resolve'
});
Promise.reject()

会生成一个 Promise 对象,且它的状态为 reject

let p = Promise.reject('error');
p.then(null, function (error){
  console.log(error) // 'error'
});

async/await

async/await 是 es7定义的方法,是基于 Promise的实现。
在 es6 Promise 的实现中,我们会写 then 方法,传入一个回调函数去处理 resolve 和 reject 结果。使用 async/await 我们会这样做

let p = Promise.resolve('resolve');
async function func () {
  let result = await p;
  console.log(result)
}
func() // 'resolve'

Node 中的处理

重点是 util.promisify 的使用,栗子如下:

const fs = require('fs');
const util = require('util');

// promisify callbackify
const readFile = util.promisify(fs.readFile);

async function asyncRead () {
  let res = await readFile('hello.txt');
  return res;
};
asyncRead()

总结

总而言之,Promise 是一个新的语法糖,使用它能够方便我们写更好维护的代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值