本文转载自:众成翻译
译者:iOSDevLog
连接:http://www.zcfy.cc/article/3814
原文:https://www.fullstackreact.com/30-days-of-react/day-15/javascript
今天,咱们将要看看咱们须要知道什么来从高层次了解Promises,因此咱们可使用这个很是有用的概念构建咱们的应用。java
昨天咱们将 fetch
库安装到咱们的 create-react-app
项目 咱们开始 第12天. 今天, 咱们将拿起从昨天讨论的概念和Promises的 艺术 .react
正如 mozilla 所定义的, 承诺
对象用于处理异步计算, 其中有一些重要的保证难以用回调方法处理 (更老式的处理异步代码的方法)。api
Promise
对象只是围绕一个值的包装, 它在实例化对象时可能也可能不知道, 并提供了一个已知的 (也称为 resolved
) 或因为失败缘由而不可用 (咱们将此称为rejected
) 后 处理该值的方法 。promise
使用 "承诺" 对象使咱们有机会将异步操做的最终成功或失败关联到功能 (不管出于何种缘由)。它还容许咱们使用相似于同步的代码来处理这些复杂的场景。浏览器
例如, 考虑下面的同步代码, 咱们在 javascript 控制台中打印出当前时间:服务器
var currentTime = new Date(); console.log('The current time is: ' + currentTime);
这是至关直接的, 并做为 new Date()
对象表示浏览器知道的时间。如今考虑咱们在其余远程机器上使用不一样的时钟。例如, 若是咱们正在作一个快乐的新年时钟, 这将是伟大的, 可以同步用户的浏览器与其余人使用一个单一的时间值为每一个人, 因此没有人错过的落球仪式。。app
假设咱们有一个方法来处理从远程服务器获取当前时间的 getCurrentTime()
时钟。如今, 咱们将用setTimeout()
来表示这一点, 它返回时间 (就像对慢速 api 发出请求同样):dom
function getCurrentTime() { // Get the current 'global' time from an API return setTimeout(function() { return new Date(); }, 2000); } var currentTime = getCurrentTime() console.log('The current time is: ' + currentTime);
咱们的console.log()
日志值将返回超时处理程序 id, 这绝对 不是 当前时间。传统上, 咱们可使用回调来更新代码, 以便在可用时间时调用:异步
function getCurrentTime(callback) { // Get the current 'global' time from an API return setTimeout(function() { var currentTime = new Date(); callback(currentTime); }, 2000); } getCurrentTime(function(currentTime) { console.log('The current time is: ' + currentTime); });
若是有其他的错误呢?咱们如何捕获错误并定义重试或错误状态?
function getCurrentTime(onSuccess, onFail) { // Get the current 'global' time from an API return setTimeout(function() { // randomly decide if the date is retrieved or not var didSucceed = Math.random() >= 0.5; if (didSucceed) { var currentTime = new Date(); onSuccess(currentTime); } else { onFail('Unknown error'); } }, 2000); } getCurrentTime(function(currentTime) { console.log('The current time is: ' + currentTime); }, function(error) { console.log('There was an error fetching the time'); });
如今, 若是咱们想根据第一个请求的值提出请求怎么办?做为一个简短的示例, 让咱们再次重用 getCurrentTime()
函数 (就好像它是第二个方法, 但容许咱们避免添加另外一个复杂的函数):
function getCurrentTime(onSuccess, onFail) { // Get the current 'global' time from an API return setTimeout(function() { // randomly decide if the date is retrieved or not var didSucceed = Math.random() >= 0.5; console.log(didSucceed); if (didSucceed) { var currentTime = new Date(); onSuccess(currentTime); } else { onFail('Unknown error'); } }, 2000); } getCurrentTime(function(currentTime) { getCurrentTime(function(newCurrentTime) { console.log('The real current time is: ' + currentTime); }, function(nestedError) { console.log('There was an error fetching the second time'); }) }, function(error) { console.log('There was an error fetching the time'); });
以这种方式处理 异步 会很快变得复杂。此外, 咱们能够从之前的函数调用中获取值, 若是咱们只想获得一个... 在处理应用启动时尚未的值时, 有不少棘手的状况须要处理。
使用承诺, 另外一方面帮助咱们避免了不少这种复杂性 (虽然不是一个银弹解决方案,参考《人月神话》)。之前的代码, 这能够被称为意大利面条代码能够变成一个更整洁, 更同步的前瞻版本:
function getCurrentTime(onSuccess, onFail) { // Get the current 'global' time from an API using Promise return new Promise((resolve, reject) => { setTimeout(function() { var didSucceed = Math.random() >= 0.5; didSucceed ? resolve(new Date()) : reject('Error'); }, 2000); }) } getCurrentTime() .then(currentTime => getCurrentTime()) .then(currentTime => { console.log('The current time is: ' + currentTime); return true; }) .catch(err => console.log('There was an error:' + err))
之前的源代码示例对正在发生的事情进行了一些清理和清除, 避免了许多棘手的错误处理/捕获。
为了得到成功的值, 咱们将使用Promise
实例对象上的 then()
功能。then()
函数被调用, 不管返回值是Promise
自己。例如, 在上面的示例中, getCurrentTime()
函数解析为currentTime()
值 (在成功完成时), 并在返回值 (这是另外一个承诺) 上调用then()
函数, 依此类推等等。
要捕获在承诺链中任何地方发生的错误, 咱们可使用catch()
方法。
咱们在上面的例子中使用一个承诺链, 以建立一个 链 的行动, 被称为一个接一个。
承诺链听起来很复杂, 但基本上很简单。实质上, 咱们能够连续地 "同步" 调用多个异步操做。对then()
的每次调用都用之前的then()
函数的返回值来调用。
例如, 若是咱们想操纵getCurrentTime()
调用的值, 咱们能够在链中添加一个连接, 以下所示:getCurrentTime() .then(currentTime => getCurrentTime()) .then(currentTime => { return 'It is now: ' + currentTime; }) // this logs: "It is now: [current time]" .then(currentTimeMessage => console.log(currentTimeMessage)) .catch(err => console.log('There was an error:' + err))
承诺在任何特定的时间都只应该在三种状态之一:
一个 待定 的承诺只能致使一个知足状态或一个被拒绝的状态 一次且仅一次 , 这能够避免一些至关复杂的错误场景。这意味着, 咱们只能返回一个承诺一次。若是咱们想从新运行一个使用承诺的函数, 咱们须要建立一个 新 的。
咱们可使用 Promise
构造函数来建立新的承诺 (如上面的示例所示)。它接受一个有两个参数来运行的函数:
onSuccess
(or resolve
) 函数将在成功解析后被调用onFail
(or reject
) 函数在失败拒绝后被调用从上面回顾咱们的函数, 咱们能够看到, 若是请求成功, 咱们调用 resolve()
函数, 若是该方法返回错误条件, 则调用 reject()
函数。
var promise = new Promise(function(resolve, reject) { // call resolve if the method succeeds resolve(true); }) promise.then(bool => console.log('Bool is true'))
如今咱们知道了什么是承诺, 如何使用, 以及如何建立它们, 咱们实际上可使用昨天安装的 fetch()
库。