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

栏目: JavaScript · 发布时间: 6年前

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

原文戳这里

[译]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函数。 简单。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Paradigms of Artificial Intelligence Programming

Paradigms of Artificial Intelligence Programming

Peter Norvig / Morgan Kaufmann / 1991-10-01 / USD 77.95

Paradigms of AI Programming is the first text to teach advanced Common Lisp techniques in the context of building major AI systems. By reconstructing authentic, complex AI programs using state-of-the-......一起来看看 《Paradigms of Artificial Intelligence Programming》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码