javascript ES6 新特性之 Promise,ES7 async / await

es6 一经推出,Promise 就一直被你们所关注。那么,为何 Promise 会被你们这样关注呢?答案很简单,Promise 优化了回调函数的用法,让本来须要纵向一层一层嵌套的回调函数实现了横向的调用,也就是链式调用。es6

咱们先来看下面的代码:dom

1 function getData(){ 2     setTimeout(()=>{ 3         var name = "zhangsan"; 4     }, 1000) 5 } 6 
7 getData();

 

在上面的代码中,咱们模拟了一个异步时间,一秒后输出 name = "zhangsan"; 那如何当咱们调用 getData() 方法的时候拿到这个 name 值呢,这时可能会有人说 return 出来就能够了,以下:异步

1 function getData(){ 2     setTimeout(()=>{ 3         var name = "zhangsan"; 4     }, 1000); 5     return name 6 } 7 
8 console.log(getData()); // ReferenceError: name is not defined

 

结果却报错,这时因为当咱们执行 getData() 函数的时候,因为 setTimeout 异步执行,因此先执行第五行的 return name;一秒以后才声明 name = "zhangsan"; 因此会 name is not defined 的错。async

那有人可能就会说把 return 放到 setTimeout 里面执行,以下:函数

1 function getData(){ 2     setTimeout(()=>{ 3         var name = "zhangsan"; 4         return name 5     }, 1000); 6 } 7 
8 console.log(getData()); // undefined

仍然拿不到 name 值,报 undefined 的错,这个缘由就很简单了,由于执行 getData() 的时候,方法没有返回值,因此报 undefined,一秒以后再执行 setTimeout。优化

 

经过以上报错咱们能够知道,setTimeout 执行完成后才能拿到 name 的值,因此咱们就须要在执行结束后再经过回调的方式拿到 name 的值,以下:spa

 1 function getData(callback){  2     setTimeout(()=>{  3         var name = "zhangsan";  4  callback(name)  5     }, 1000)  6 }  7 
 8 getData((data)=>{  9     console.log(data) // zhangsan
10 });

 

咱们在 getData() 方法内出入一个回调函数,当 setTimeout 执行结束后调用此方法并将 name 值传入,这样咱们就能拿到 name 值了。这里咱们用到了 ES6 的另外一个特性 箭头函数,咱们姑且先将它 ( ) => { } 和 function( ){ } 看作是等价的。code

 

上述方法能够解决咱们的问题,可是在代码上咱们就须要再多些一个回调函数,这样看起来很不友好,因此 ES6 为咱们提供了 Promise 这个特性。blog

1 var p = new Promise((resolve, reject) => { 2     setTimeout(() => { 3         var name = "zhangsan"; 4  resolve(name) 5     }, 1000) 6 }); 7 p.then((data) => { 8  console.log(data); 9 });  // zhangsan

 

上面的代码等同于下面的:get

 1 function getData(resolve, reject) {  2     setTimeout(() => {  3         var name = "zhangsan";  4  resolve(name)  5     }, 1000)  6 }  7 
 8 var p = new Promise(getData);  9 
10 p.then((data)=> { 11  console.log(data); 12 });  // zhangsan

咱们能够看出,Promise 构造函数接受一个函数做为参数,函数里面有两个参数 resolve 和 reject ,其中 resolve 做为执行成功的函数, reject 做为执行失败的函数。以下:

 1 function getData(resolve, reject) {  2     setTimeout(() => {  3         var name = "zhangsan";  4         if(Math.random() < .5){  5  resolve(name)  6         } else{  7             reject("获取 name 失败")  8  }  9     }, 1000) 10 } 11 
12 var p = new Promise(getData); 13 
14 p.then((data)=> { 15     console.log(data);   // zhangsan
16 },(data)=>{ 17     console.log(data);   // 获取 name 失败
18 }) ;

咱们定义一个随机数,当随机数小于 0.5 时会走 p.then() 的第一个函数,也就是正确的 resolve,当随机数大于 0.5 时,会走第二个函数,也就是错误的 reject。

Promise 除了 then 以外还提供了一个一个 catch 的方法,以下:

 1 function getData(resolve, reject) {  2     setTimeout(() => {  3         var name = "zhangsan";  4  resolve(name)  5     }, 1000)  6 }  7 
 8 var p = new Promise(getData);  9 
10 p.then((name)=> { 11     console.log(name);   // zhangsan
12  console.log(age) 13 }).catch((reason)=>{ 14     console.log(reason)  // ReferenceError: age is not defined
15 }) ;

在上面的代码中咱们在 p.then() 的方法内输出了一个 age ,可是这个 age 咱们既没有在全局定义,也没有经过传值的方式传过来,若是咱们不写底下的 catch() 方法的话会报 ReferenceError: age is not defined,同时程序会崩掉,加上 .chath 方法后 ReferenceError: age is not defined 会在此方法内输出,程序并不会崩掉,这个就相似于咱们经常使用的 try / catch 方法。

 

在 ES7 中,还给咱们提供了更为方便的异步操做方法 async / await ;以下:

 1 async function getData() {  2     return new Promise((resolve, reject) => {  3         setTimeout(() => {  4             var name = "zhangsan";  5  resolve(name)  6         }, 1000)  7  })  8 }  9 
10 async function test() { 11     var data = await getData(); 12  console.log(data); 13 } 14 
15 test();  // zhangsan

咱们将以前的代码改成上面这样,输出结果依然是 zhangsan,这里使用了 async / await 的组合,咱们将上面的代码简化一下:

 1 async function getData() {  2     var name = "zhangsan";  3     return name;  4 }  5 
 6 console.log(getData());  // Promise { 'zhangsan' }
 7 
 8 async function test(){  9     var data = await getData(); 10  console.log(data); 11 } 12 
13 test();  // zhangsan

 

咱们在 function getData( ){ } 前面加了一个 async 的字段,该函数就被认定为一个异步函数,而后在调用 getData( ) 的方法前面加一个 await 的字段,这就是一个异步操做,意思就是等 getData( ){ } 异步函数执行完之后再调用此方法,这样咱们在 getData() 的函数内加一个 setTimeout 的异步方法后,也是等异步方法执行完之后在调用,这样就能拿到 name = "zhangsan" 的值了。

相关文章
相关标签/搜索