[译]ES6入门(第二部分)

作者: 范蓄能 | 来源:发表于2018-10-03 12:10 被阅读19次

    原文戳这里

    [译]ES6入门(第一部分)

    [译]ES6入门(第三部分)

    这篇文章的第一部分出现在这里。 我在那里介绍了一些有趣的功能:)

    我将在这篇文章中介绍的主题包括:

    1、Promises

    2、Async / Await

    Promises

    Promise是ES6中的一个有用功能。它们用于进行异步操作,例如API请求,文件处理,下载图像等。

    那么,什么是异步? (继续,如果你已经知道)

    异步操作是需要一些时间才能完成的操作。

    例如,假设您正在定义向服务器发出API请求的函数。该函数不会立即返回结果,因为从服务器获取响应需要几秒钟。

    因此,如果您正在调用该函数并将其值(即)返回的结果分配给某个变量,那么它将是未定义的。因为Javascript不知道该函数正在处理一些异步操作。

    那我们该如何处理呢?

    让我们先谈谈一些历史。

    在Promise之前,程序员习惯于定义回调。回调是Javascript中的常规函数,它在异步操作完成时执行。

    例如,您定义了一个向服务器发出API请求的函数。然后你设置了一个回调函数,它将在我们从服务器获得响应时执行。

    所以在上面的例子中,Javascript不会停止执行,直到我们从API获得响应。我们已经定义了一个函数(回调),它将在我们得到响应后执行。我想你明白了。

    那么,Promise是什么?

    Promise是有助于执行异步操作的对象。

    从技术上讲,它们是表示异步操作完成的对象。 (如果你不明白,请继续往下阅读一会儿)

    在解释如何定义Promise之前,我将解释Promise的生命周期。

    在Promise中有三种状态:

    1、挂起:在这种状态下,promise只是执行异步操作。例如,它正在向服务器发出一些API请求或从cdn下载一些图像。 从这个状态Promise可以转移到完成状态或拒绝状态

    2、完成:如果Promise已达到此状态,则表示异步操作已完成,并且得到了输出的结果。例如,我们有了来自API的响应。

    3、拒绝:如果Promise已达到此状态,则表示异步操作未成功,并且我们得到导致操作失败的错误。

    好的..让我们看一些代码。

    const apiCall = new Promise(function(resolve, reject) {
     // 异步操作在这里定义..
    });
    

    通过使用new关键字创建构造函数来定义Promise。 然后构造函数将有一个函数(我们称之为执行函数。)

    异步操作在执行函数内定义。

    请注意,执行函数有两个参数resolve和reject。

    第一个参数resolve实际上是一个函数。 它在执行函数内部调用,它表示异步操作成功,我们得到了结果。 resolve函数有助于Promise从挂起状态转为完成状态。 希望你明白了。:)

    像resolve一样,reject也是一个函数。 它也在执行函数内部调用,它表示异步操作不成功,我们遇到了错误。 reject函数有助于Promise从挂起状态转为拒绝状态。:)

    const apiCall = new Promise(function(resolve, reject) {
     if ( API request to get some data ) {
      resolve("The request is successful and the response is "+ response);
     }
     else {
      reject("The request is not successful. The error is "+error);
     }
    });
    

    在上面的代码中,您可以看到我们在执行函数中完成了一些异步操作。 如果我们从服务器获得响应,则调用resolve函数。 如果有错误,则会使用错误消息调用reject函数。

    我们已经完成了Promise。 让我们看看如何执行Promise并处理输出。

    // 调用promise.
    apiCall
    

    就是这样。 结束了。 :) :)

    开玩笑。 还没结束。

    在上面的代码中,调用函数并执行promise(即执行函数)。 然后根据输出调用resolve或reject函数。

    但是你可以看到我们没有处理promise中返回的输出。

    例如,如果我们从API获得响应,那么我们必须处理响应。 或者如果我们得到错误,我们需要正确处理它。

    那我们该如何处理呢?

    我们使用处理器来获取promise的输出。

    处理器是在某些事件发生时执行的函数,例如单击按钮,移动光标等。

    因此,当resolve函数被调用或reject函数被调用时,我们可以使用处理器来处理。

    简单。:)

    我们来看一些代码

    // 调用promise,并使用handlers.
    apiCall.then(function(x) {console.log(x); })
    

    在上面的代码中,我们将一个处理器then附加到promise。处理器then有一个函数参数。函数参数本身有一个参数x。

    发生了什么事?

    当在promise内调用resolve函数时,处理器then执行其函数参数。

    我会再解释一次。

    处理器then监听resolve函数被调用时的事件。 因此,当调用resolve函数时,处理器then执行其函数参数。

    apiCall.then(function(x) {console.log(x); })
    // 输出
    The request is successful and the response is {name: "Jon Snow"}
    

    同样,还有另一个处理器catch。

    Catch监听reject函数。

    Catch函数在reject函数被调用时执行其函数参数。

    apiCall.then(function(x) {console.log(x); }).catch(function(x) {console.log(x); })
    // 假设这个请求没有成功 (在promise中reject函数被调用. )
    输出:
    The request is not successful
    

    我想你明白了。

    上面的代码不太可读。 所以让我们尝试重构它。

    apiCall
    .then(function(x) {
     console.log(x); 
    })
    .catch(function(x) {
     console.log(x);
    }) 
    

    啊......现在可读了。 大多数程序员都这样写。

    好吧..所以我觉得你已经走了很长的路。

    我们来回顾一下。

    1、使用带有函数参数的new关键字定义Promise。 然后函数本身有两个函数参数resolve和reject。

    2、操作成功时应调用resolve函数。

    3、操作失败时应调用reject函数。

    4、处理器then监控resolve函数。

    5、处理器catch监控reject函数。

    6、确保代码的可读性:) :)

    这是可运行的示例。 如果您不熟悉,请练习。

    var ApiCall = new Promise(function(resolve, reject) {
      
      var request = new XMLHttpRequest();
      request.open('GET', 'https://api.github.com/users/srebalaji');
    
      request.onload = function() {
        if (request.status == 200) {
          
          resolve(request.response);
        } else {
          reject(Error(request.statusText));
        }
      }
    
      request.send();
    });
    
    ApiCall
    .then(function(x) {
      document.getElementById('response').innerHTML = x;
    })
    .catch(function(x) {
        document.getElementById('response').innerHTML = x;
    })
    

    希望你能理解这个例子。 它直截了当。

    Async / Await

    如果您了解Promises,那么Async / Await非常简单。 如果你没有弄明白Promises,Async / Await可以帮助你理解它。 也许你也可以彻底地躲开Promises。:)

    Async

    Async关键字使任何函数只返回promises。

    例如,请看以下代码

    async function hello() {
     return "Hello Promise..!"
    }
    

    函数hello将返回一个promise。

    上面的代码相当于下面的代码。

    function hello() {
     return new Promise(function(resolve, reject) {
     // executor function body
     });
    }
    

    非常简单是吧?

    另外一个例子:

    async function hello(a, b) {
     if (a < b) {
      return "Greater";
     }
     else {
      return new Error("Not Greater");
     }
    }
    hello(14, 10)
    .then(function(x) {
     console.log("Good..! " + x); 
    })
    .catch(function(x) {
     console.log("Oops..! " + x); 
    })
    输出:
    Oops..! Not Greater. 
    // 如果你调用 hello(4, 10) 你会得到 "Good..! Greater"
    

    在上面的代码中,我们定义了一个async函数并返回了一些值或返回了一些错误。

    如果要在async函数中返回一些值,则它等同于调用resolve函数。

    如果通过使用'new'调用错误构造函数(即)返回一些错误,则它等同于reject函数。

    不要忘记async函数将返回一个promise。 当然,你也可以在async函数中调用resolve和reject函数。

    让我们看看它是如何工作的。

    async function Max(a, b) {
     if (a > b) {
      return Promise.resolve("Success");
     }
     else {
      return Promise.reject("Error");
     }
    }
    Max(4, 10)
    .then(function(x) {
     console.log("Good " + x); 
    })
    .catch(function(x) {
     console.log("Oops " + x); 
    });
    输出:
    Oops Error
    // 如果调用 Max(14, 10) 我们会得到 "Good Success" :)
    

    Await

    顾名思义,它使Javascript等到操作完成。 假设您正在使用await关键字发出API请求。 它使Javascript等待,直到您从端点获得响应。 然后它恢复执行。

    好的..让我们走得更远

    Await只能在异步函数中使用。 它在异步功能之外不起作用

    我们来看一个例子吧

    async function hello() {
     let response = await fetch('https://api.github.com/');
     // 上面一行从给定的API终端获取响应
     return response;
    }
    hello()
    .then(function(x) {
     console.log(x); 
    });
    ...
    ...
    输出:
    Response from the API.
    

    在上面的代码中,您可以看到我们在从API获取响应时使用了await。

    获取操作可能需要几秒钟才能获得响应,直到获取到响应,执行将暂停并稍后恢复。

    请注意,await操作仅停止hello函数内的执行。 hello函数外的其余代码不会受到影响。 执行在函数外部继续。 当我们得到响应时,执行内部函数参数。

    希望你明白了。

    我们来看一个例子

    function getResponse() {
      return new Promise(function(resolve, reject) {
        setTimeout(function() {
          resolve("Response from API. Executed after 5 secs");
        }, 5000);
      });
    }
    
    async function hello() {
      let response = await getResponse();
      return response;
    }
    
    hello()
      .then(function(x) {
        console.log(x);
      })
      .catch(function(x) {
        console.log(x);
      });
    console.log("Im executed before getResponse()");
    

    在上面的示例中,您可以看到我们对getResponse函数使用了await。 并且getResponse将在5秒后返回输出或错误。 因此,在此之前,执行将暂停,然后返回响应。

    让我们看一些实时的例子

    function getResponse(url) {
        return new Promise(function(success, failure) {
      var request = new XMLHttpRequest();
        request.open('GET', url);
        
      request.onload = function() {
        if (request.status == 200) {
          return success(request.response);
        } else {
          return failure("Error in processing..!" + request.status);
        }
      }
      request.onerror = function() {
        return failure("Error in processing ");
      }
      request.send();
      });
    }
    
    function getUsername(response) {
      response = JSON.parse(response);
      return response["login"];
    }
    
    function makeUsernameCaps(name) {
        return new Promise(function(success, failure) {
        // Let's assume it takes 3secs to make the username caps :) 
        setTimeout(function() {
        success(name.toUpperCase());
        }, 3000)
      });
    }
    async function apiCall(url) {
      let response = await getResponse(url); 
      let username = await getUsername(response);
      let username_in_caps = await makeUsernameCaps(username);
      return username_in_caps;
    }
    
    apiCall("https://api.github.com/users/srebalaji")
    .then(function(x) {
        console.log(x);
    })
    .catch(function(x) {
        console.log("Error - "+x);
    });
    

    在上面的例子中,您可以看到我们已经使用了多个await。 因此,对于每个await, 程序停止执行,直到收到响应然后恢复。

    在示例中尝试使用一些无效网址。 您可以看到引发错误。

    async函数中的错误处理非常简单。 如果在async函数内引发错误,或者在async函数中使用await调用的其他函数内引发错误,则会调用reject函数。 简单。

    相关文章

      网友评论

        本文标题:[译]ES6入门(第二部分)

        本文链接:https://www.haomeiwen.com/subject/qvpzoftx.html