前端JS

不深入只浅出ES6 Promise | 笔记

2017-03-15  本文已影响190人  唯泥Bernie

用例子直观的陈列 Promise 的行为作为笔记(如果能帮助新手快速了解 Promise 的使用自然最好,最终还是希望不但要学会使用还要了解规范),此行为规范基于的是 ES6 的规范,以后 JS 规范更新可能改变某些行为。原理及规范请查看考如下资料:

  1. 《You Don't Know JS: Async & Performance - Chapter 3: Promises》 这是著名的《你不知道的JavaScript》的英文原版章节。-- 这篇对于新人的缺点是过长。
  2. Promises/A+ 规范 这篇是 ES6 Promise 规范的前身。 -- 这篇对于新人的缺点是技术点不容易看懂。
  3. ES6 Promise 规范 -- 最权威的规范。
var p1 = new Promise( function(resolve, reject){
  resolve( 1 )
} )

var p2 = new Promise( function(resolve, reject){
  setTimeout( function(){
    resolve( 2 )
  }, 1000 );
} )

p1.then( function(value){
  console.log( value ); // 1
}, function(){
  // never gets here
} )

p2.then( function(value){
  console.log( value ); // 2
}, function(){
  // never gets here
} )

无论构造时候 executor 中被传入的 resolve 函数是同步地被调用还是异步地被调用,只要传入的是一个非 promise 非 thenable 的值,都会在 then 传入的第一个回调函数(onFulfilled)中获得这个值,第二个回调函数(onRejected)不会被调用到。

<br />

var p1 = new Promise( function(resolve, reject){
  reject( 'rejected because ...' )
} )

p1.then( function(value){
  console.log( value ); // never gets here
}, function(reason){
  console.log( reason ); // rejected because ...
} )

<br />

var p1 = new Promise( function(resolve, reject){
  throw new Error( 'test error' )
  resolve( 1 )
} )

var p2 = new Promise( function(resolve, reject){
  '1'.toFixed() // number has not toString method ,so it will throw exception
  resolve( 2 )
} )

p1.then( function(value){
  console.log( value ); // never gets here
}, function(error){
  console.log( error.message ) // test error
} )

p2.then( function(value){
  console.log( value ); // never gets here
}, function(error){
  console.log( error.message ) // "1".toFixed is not a function
} )

<br />

var p1 = new Promise( function(resolve, reject){
  resolve( 1 )
} )

var p11 = p1.then( function(value){
  return value * 3;
}, funtion(){
  // never gets here
} );

p11.then( function(value){
  console.log( value ); // 3
}, function(){}{
  // never gets here
} )
/*
上述改成链式调用的写法就是:

p1.then( function(value){
  return value * 3;
} ).then( function(value){
  console.log( value ); // 3
} )
*/


var p2 = new Promise( function(resolve, reject){
  '1'.toFixed() // number has not toString method ,so it will throw exception
  resolve( 2 ) // never gets here
} )

// p2 rejected的情况,以下采用链式调用写法
p2.then( function(){
  // never gets here
}, function(error){
  console.log( error.message ) // "1".toFixed is not a function
  return 4;
} ).then( function(value){
  console.log( value ); // 4
} )

// 如果 onFullfilled, onRejected 没有返回则会获得 undefined, 
new Promise( function(resolve, reject){
  resolve( 1 )
} ).then( function(value){
  console.log( value ); // 1
}, function(){
  // never gets here
} ).then( function(value){
  console.log( value ); // undefined
}, function(){
  // never gets here
} )

一个 promise.then 中的两个回调函数只有一个会被调用,因为 promise 的状态要么是成功的,要么是失败的,不会在成功失败间相互转换。

<br />

new Promise( function(resolve, reject){
  resolve( 1 );
} ).then( function(){
  throw new Error( 'test error1' );
  return 2; // never gets here
} ).then( function(){
  // never gets here
}, function(error){
  console.log( error.message ); // test error1
} )

new Promise( function(resolve, reject){
  throw new Error( 'test error2' );
  resolve( 1 ); // never gets here
} ).then( function(){
  // never gets here
}, function(error){
  console.log( error.message ); // test error2
  throw new Error( 'test error3' );
} ).then( function(error){
  // never gets here
}, function(error){
  console.log( error.message ); // test error3
} )

<br />

new Promise( function(resolve, reject){
  resolve(1);
} ).then(
  null,
  null
).then( function(value){
  console.log( value ); // 1
} )

new Promise( function(resolve, reject){
  throw new Error( 'test error' );
  resolve(1); // never gets here
} ).then().then( function(){
  // never gets here
}, function(error){
  console.log( error.message ); // test error
} )

<br />

var p0 = new Promise( function(res,rej){ res(0); } ); // fulfilled promise
var p1 = new Promise( function(resolve, reject){
  resolve( p0 );
} );
p1.then( function(value){
  console.log( value ); // 0
}, function(){
  // never gets here
} );

var p2 = new Promise( function(res,rej){ throw new Error('test error') } ); // rejected promise
new Promise( function(resolve, reject){
  resolve( p2 );
} ).then( function(){
  // never gets here
}, function(error){
  console.log( error.message ); // test error
} )

<br />

var p0 = new Promise( function(res,rej){ res(0); } );
new Promise( function(resolve, reject){
  resolve( 1 );
} ).then( function(){
  return p0;
} ).then( function(value){
  console.log( value ); // 0
} )

new Promise( function(resolve, reject){
  throw new Error( 'make rejected' );
} ).then( null, function(error){
  return p0
} ).then( function(value){
  console.log( value ); // 0
} )

<br />

var p1 = new Promise( function(){
  throw new Error( 'make rejected' );
} );

p1.then( null, function( error ){
  console.log( error.message ); // make rjected
} );

p1.catch( function(error) {
  console.log( error.message ); // make rjected
} );
// p1.then(null,onRejected) 和 p1.catch(onRejected) 是完全等价的。


// 链式调用
new Promise( function(resolve, rejected){
  resolve( 0 );
} ).then( function(value){
  // some code here, may generate some error
  return value++;
} ).then( function(value){
  // some code here, may generate some error
  return value++;
} ).then( function(value){
  // some code here, may generate some error
  return value++;
} ).then( function(value){
  // some code here, may generate some error
  return value++;
} ).catch( function(error){
  // 上面任何一个 then 都没有设置 onRejected 回调函数,意味着,一旦有一个 onFulfilled 里面一旦报错,则一个失败状态的 promise 会得不到处理,一直延续到最后一个被 catch 处理。
  // 如果理解不了,则自行拆解每个 then
} )
var p1 = Promise.resolve( 42 );
p1.then( function(value){
  console.log( value ); // 42
} );

var p2 = Promise.resolve( p1 );
p2 === p1; // true
var p1 = Promise.reject( 'make rejected' );
p1.catch( function(reason){
  console.log( reason ); // make rejected
} );

var p2 = Promise.reject( p1 );
p2.catch( function(reason){
  console.log( reason ); // p1: Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "make rejected"}
} );

<br />

<br />

<br />
文中总结了 promise 的一般用法,没有涉及到异步和 thenable 的概念。异步的概念我还需要进一步看些资料,一时我也没有钻的比较深。thenable 除非你项目是老项目,里面会用到 promise 出现前的一些内容(譬如 jQuery 中的 defer),一般是不太会涉及到这个概念,你就先理解成 thenable 对象是一个带 then 方法的对象,但是它本身不是 Promise 对象,具体还是希望各位看官查看文章开始所列的资料。

上一篇下一篇

猜你喜欢

热点阅读