es6的学习笔记(三)

promise

promise,按照我的理解来说,是一种异步回调更优雅的写法

An alternative to callbacks and events

fetch(‘/items’)类似于ajax中的get,不过返回值是一个promise.

fetch('/items').then(
  //do something
  ()=>console.log('hello')//此处加;是会报错的,一句话的箭头函数不应该有分号
)
//写法一
const p = fetch('/items')
p.then(res => {
// handle response
})
p.catch(error => {
// handle error
})
//写法二
const p = fetch('/items')
p.then(
res => {
// handle response
},
err => {
// handle error
}
) //上述两种写法是等价的

then和catch函数分别处理p的正确和错误。.then和.catch的返回值均是一个Promise,所以它的级联(chaining)变得很简单。

p.then(null, error => {
// handle error
})//此写法等价于p.catch(error=>{})

promise的创建方法

  1. 使用new Promise创建。Promise本质上是一个对象,可以使用New字符进行创建
new Promise(function(resolve,reject){
  setTimeout(function(){
    if(Math.random()>0.5)
      resolve('random success');
    else
      reject(new Error('failed'));
    },1000);
  }).then(data=>console.log(data),err=>console.log(err));
  1. 也可以使用Promise.resolve和.reject直接创建,这种形式的Promise会直接执行。
Promise.resolve({result:'false'}).then((data)=>console.log(data.result))//这种形式的Promise会立即执行,结束后执行then里面的函数

then,catch函数的返回值

在一个then或者catch中,函数可以返回一个数值,抛出一个err,或者返回一个thenable的对象。
不论resolve的返回值是什么,均会执行下一个then函数,因为使用了resole),而reject的返回值不论是什么,都会执行catch,而then和catch是根据其返回值(reaction)来决定下一步执行then还是catch函数。

  1. 当返回值是一个数值的时候:其返回值会作为下一个then函数的输入数据,不会触发catch函数。如下面的代码,第一个resolve的返回值是数值2
    之后执行then,返回2*7=14,因为返回了一个数值,继续执行下面的then,一直到最后,输出x=11。
Promise
  .resolve(2)
  .then(x => x * 7)
  .then(x => x - 3)
  .then(x => console.log(x))
// <- 11
  1. 当返回值是一个Promise的对象的时候,会等待其中的resolve或者reject函数执行。
Promise
  .resolve(2)
  .then(x => new Promise(function (resolve) {
    setTimeout(() => resolve(x * 1000), x * 1000)
  }))
  .then(x => console.log(x))
// <- 2000

上述函数的第二个返回值是是一个promise对象,2s之后会执行resolve函数,返回值是2000,所以继续执行then,输出2000.

  1. 返回值(英文是reaction,类似于一个动作的反应,我感觉转换成程序语言,就是返回值的意思)是一个err,就会执行catch函数,而then函数不会被执行。
Promise.resolve(new Error('failed'))
  .then(()=>{throw new Error('failed')})
.then(null,data=>console.log(data));

关于then,catch,resolve,reject的一些实例解释

//实例1,通过new新建Promise,在resolver中,执行reject函数并reaction一个错误,
//所以接下来会执行catch函数,data=上一步中的返回值(reaction)
//也就是new Error('oops')
new Promise((resolve, reject) => reject(new Error('oops')))
  .catch(err => console.error(err))
//这段代码实现了和实例1一样的功能,也就是说,在resolver中执行throw,
//抛出一个错误,也会导致程序直接执行接下来的catch函数,与reject('返回值')的效果相同
new Promise((resolve, reject) => { throw new Error('oops'); })
  .catch(err => console.error(err))  

//这段代码在then函数中抛出了一个错误,所以会在下一步执行catch函数
  Promise
    .resolve(2)
    .then(x => { throw new Error('failed'); })
    .catch(err => console.error(err))

promise.all和race

The Promise.all method takes an array of promises and returns a single promise p. When all promises passed to Promise.all are fulfilled, p becomes fulfilled as well with an array of results sorted according to the provided promises. If a single promise becomes rejected, p settles with its rejection reason immediately.
promise.all的参数是一系列的promise数组,返回值是一个promise,当所有的promise完成了,然后他们的返回值会存储在一个数组中,顺序就是放入promise.all中的顺序,相反,如果其中一个错误,p就会立刻返回错误。

Promise
  .all([
    Promise.resolve(12),
    Promise.resolve(10),
  ])
  .then(products => console.log(products[0], products[1]))

这样的好处就是可以在好几个promise完成之后再一同处理数据。
所以,promise.all的输出值有三种情况:

  1. 输出里面promise的返回值
  2. 输出一个单独的错误
  3. 停留在pending的状态,因为其中有至少一个没有执行。

promise.race与all很相似,只是第一个结束的promise会直接输出,也就是说,返回值就是第一个promise完成的返回值,如果出错,也是返回第一个错误,之后的不会执行。所以叫race

Promise
  .race([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise(resolve => setTimeout(() => resolve(2), 2000))
  ])
  .then(result => console.log(result))
  // <- 1

**补充:容易误会的一点,Promise.then.catch中的then,catch都是对上一个promise的处理,与Promise(f1,f2),f1就是then,f2就是catch,这两者是等价的。