【全栈React】第15天: Promise简介

本文转载自:众成翻译
译者: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

Promise

正如 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');
});

以这种方式处理 异步 会很快变得复杂。此外, 咱们能够从之前的函数调用中获取值, 若是咱们只想获得一个... 在处理应用启动时尚未的值时, 有不少棘手的状况须要处理。

进入Promise

使用承诺, 另外一方面帮助咱们避免了不少这种复杂性 (虽然不是一个银弹解决方案,参考《人月神话》)。之前的代码, 这能够被称为意大利面条代码能够变成一个更整洁, 更同步的前瞻版本:

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))

单使用Guarantee

承诺在任何特定的时间都只应该在三种状态之一:

  • 待定
  • 已完成 (已解决)
  • 已拒绝 (错误)

一个 待定 的承诺只能致使一个知足状态或一个被拒绝的状态 一次且仅一次 , 这能够避免一些至关复杂的错误场景。这意味着, 咱们只能返回一个承诺一次。若是咱们想从新运行一个使用承诺的函数, 咱们须要建立一个 的。

建立一个Promise

咱们可使用 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() 库。

相关文章
相关标签/搜索