ES6-Promise

177 阅读4分钟

一、介绍

主要解决的问题:嵌套深渊的问题

二、特性:

1、基本

1.Promise对象表示未来某个将要发生的事件,但在创建(new)Promise时,作为Promise参数传入的函数是会被立即执行的,只是其中执行的代码可以是异步代码

2.Promise 三种状态Pending,resolved,rejected

3.Promise 的状态具有不可逆性

var p1 = new Promise(function(resolve, reject){
  resolve("success1");
  resolve("success2");
});

var p2 = new Promise(function(resolve, reject){
  resolve("success");
  reject("reject");
});

p1.then(function(value){
  console.log(value);
});

p2.then(function(value){

  console.log(value);
});
控制台返回结果:
"success1"
"success"

2、链式调用

var p = new Promise(function(resolve, reject){
  resolve(1);
});
p.then(function(value){               //第一个then
  console.log(value);
  return value*2;
}).then(function(value){              //第二个then
  console.log(value);
}).then(function(value){              //第三个then
  console.log(value);
  return Promise.resolve('resolve'); 
}).then(function(value){              //第四个then
  console.log(value);
  return Promise.reject('reject');
}).then(function(value){              //第五个then
  console.log('resolve: '+ value);
}, function(err){
  console.log('reject: ' + err);
})
控制台返回结果:
1
2
undefined
"resolve"
"reject: reject"

注意:Promise.then方法 会返回一个新的promise对象

3、Promise then() 回调异步性

5.Promise then() 回调异步性
var p = new Promise(function(resolve, reject){
  resolve("success");
});

p.then(function(value){
  console.log(value);
});

console.log("which one is called first ?");
后台返回:

"which one is called first ?"
"success"

4、Promise 中的异常

var p1 = new Promise( function(resolve,reject){
  foo.bar();
  resolve( 1 );      
});

p1.then(
  function(value){
    console.log('p1 then value: ' + value);
  },
  function(err){
    console.log('p1 then err: ' + err);
  }
).then(
  function(value){
    console.log('p1 then then value: '+value);
  },
  function(err){
    console.log('p1 then then err: ' + err);
  }
);

var p2 = new Promise(function(resolve,reject){
  resolve( 2 );    
});
p2.then(
  function(value){
    console.log('p2 then value: ' + value);
    foo.bar();
  }, 
  function(err){
    console.log('p2 then err: ' + err);
  }
).then(
  function(value){
    console.log('p2 then then value: ' + value);
  },
  function(err){
    console.log('p2 then then err: ' + err);
    return 1;
  }
).then(
  function(value){
    console.log('p2 then then then value: ' + value);
  },
  function(err){
    console.log('p2 then then then err: ' + err);
  }
);
控制台的输出结果:
p1 then err: referfence error
p2 then value: 2
p1 then then value: 1
p2 then then err: referfence error
 
p2 then then then value: 1

1.漏斗调用,程序块出错,程序跳到最近一级catch,后续代码在下一级then中执行

2.如果捕获代码有return  操作,后续的then将继续执行

5、Promise.resolve()

代码示例:

var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
  resolve(1);
});
var p4 = new Promise(function(resolve, reject){
  resolve(p1);
});

console.log(p1 === p2); 
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then(function(value){
  console.log('p4=' + value);
});
p2.then(function(value){
  console.log('p2=' + value);
})

p1.then(function(value){
  console.log('p1=' + value);
})
控制台输出结果:

true
false
false
false
p2=1
p1=1
p4=1

知识点:

  • Promise.resolve(...) 可以接收一个值或者是一个Promise对象作为参数。当参数是普通值时,它返回一个resolved状态的Promise对象,对象的值就是这个参数;当参数是一个Promise对象时,它直接返回这个Promise参数

  • 为什么p4的then*最先调用,但在控制台上是最后输出结果的呢?因为p4的resolve中接收的参数是一个Promise对象p1,resolve会对p1”拆箱“,获取p1的状态和值,但这个过程是异步的


6、resolve vs reject

var p1 = new Promise(function(resolve, reject){
  resolve(Promise.resolve('resolve'));
});
var p2 = new Promise(function(resolve, reject){
  resolve(Promise.reject('reject'));
});
var p3 = new Promise(function(resolve, reject){
  reject(Promise.resolve('resolve'));
});
p1.then(
  function fulfilled(value){
    console.log('fulfilled: ' + value);
  }, 
  function rejected(err){
    console.log('rejected: ' + err);
  }
);
p2.then(
  function fulfilled(value){
    console.log('fulfilled: ' + value);
  }, 
  function rejected(err){
    console.log('rejected: ' + err);
  }
);
p3.then(
  function fulfilled(value){
    console.log('fulfilled: ' + value);
  }, 
  function rejected(err){
    console.log('rejected: ' + err);
  }
);

控制台输出:

p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject

7、Promise的不同写法

Promise.resolve     返回一个Promise对象

new Promise((res,rej)=>{ })    适合异步执行   如:调用网络请求   调用native插件

8、Promise对作用域的影响

注意事项:

1.在ES6的类中,经常有以下写法:a.then(b).then(c)

注意  方法b  如果是类方法, 方法体内的this指向变为  undefined

解决办法: a.b用autobind   b. 使用箭头函数,改变this作用域

9、Promise.all && race

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。

Promise

.all([runAsync1(), runAsync2(), runAsync3()])

.then(function(results){

console.log(results);

});

主要使用场景: 并行任务的效率优化<参见客户管理-登录>部分代码,获取坐标和初始化请求并行执行。

race方法

all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。race的用法与all一样

  • 解决图片加载超时问题:

demo代码如下:

//请求某个图片资源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise
.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});