30天入坑React ---------------day15 Promises

30天入坑React ---------------day15 Promises

30天入坑React ---------------day15 Promises

这篇文章是30天React系列的一部分 。

在本系列中,我们将从非常基础开始,逐步了解您需要了解的所有内容,以便开始使用React。如果您曾经想学习React,那么这里就是您的最佳选择!

下载免费的PDF

30天入坑React ---------------day15 Promises

promise(承诺)简介

在Github上编辑此页面

今天,我们将看一下从高层次了解Promise需要了解的内容,因此我们可以使用这个非常有用的概念构建我们的应用程序。

昨天我们将fetch库安装到我们create-react-app第12天开始的项目中。今天我们就从昨天拿起讨论的概念和技术承诺

什么是promise(承诺)

正如Mozilla所定义的,一个Promise对象用于处理异步计算,这些计算具有一些重要的保证,这些保证很难用回调方法处理(处理异步代码的老派方法)。

一个Promise目的是简单地围绕可或可不当对象被实例化,并提供用于处理的值的方法是已知的一个值的包装它是已知的(也称为resolved)或为失败原因不可用的(我们将参照对此as rejected)。

使用Promise对象使我们有机会将异步操作的功能与最终的成功或失败相关联(无论出于何种原因)。它还允许我们通过使用类似同步的代码来处理这些复杂的场景。

例如,考虑以下同步代码,我们在JavaScript控制台中打印出当前时间:

var currentTime = new Date();
console.log('The current time is: ' + currentTime);

这非常简单,因为new Date()对象代表浏览器知道的时间。现在考虑我们在其他远程机器上使用不同的时钟。例如,如果我们正在制作新年快乐时钟,那么能够将用户的浏览器与所有人同步使用单个时间值对所有人进行同步非常棒,因此没有人错过了落球仪式。

PS:时代广场新年除夕球落下,表示新的一年的开始

 

假设我们有一个方法来处理获取当前时间的方法,该时钟getCurrentTime()从远程服务器获取当前时间。我们现在用一个setTimeout()返回时间来表示这个(就像它向一个缓慢的API发出请求):

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(承诺)

另一方面,使用promises可以帮助我们避免很多这种复杂性(尽管不是银弹解决方案)。以前的代码,可以称为意大利面条代码,可以变成更整洁,更同步的版本:

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

30天入坑React ---------------day15 Promises

这个先前的源代码示例对于发生了什么有点清晰和明确,并避免了许多棘手的错误处理/捕获。

为了抓住成功的价值,我们将使用实例对象then()上的可用功能Promisethen()无论promise本身的返回值是什么,都会调用该函数。例如,在上面的示例中,getCurrentTime()函数使用currentTime()值(成功完成时)解析并then()在返回值(这是另一个promise)上调用函数,依此类推。

为了捕获promise链中任何地方发生的错误,我们可以使用该catch()方法。

我们在上面的例子中使用了一个promise链来创建一个接一个地调用的动作。承诺链听起来很复杂,但它基本上很简单。从本质上讲,我们可以连续“同步”多个异步操作的调用。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​​​​​​​(承诺)在任何给定时间都只有三种状态之一:

 

  • pending                   有待
  • fulfilled (resolved)       履行(已解决)
  • rejected (error)           拒绝(错误)

​​​​​​​​​​​​​

一个悬而未决的承诺永远只能导致无论是完成状态或拒绝状态一次且仅一次,可避免一些非常复杂的错误情况。这意味着我们只能回复一次承诺。如果我们想重新运行使用promises的函数,我们需要创建一个函数。

创造一个promise​​​​​​​(承诺)

我们可以使用Promise构造函数创建新的promise(如上所示)。它接受一个将使用两个参数运行的函数:

  • 成功解析时要调用的onSuccess(或resolve)函数
  • 在失败拒绝时调用的onFail(或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'))

既然我们知道promise​​​​​​​(承诺)是什么,如何使用,以及如何创建它们,我们实际上可以开始使用fetch()我们昨天安装的库。DD

30天入坑React ---------------day15 Promises

学习REACT正确的方法

React和朋友的最新,深入,完整的指南。

下载第一章

❮上一个

下一章:

显示远程数据

下一个 ❯

本教程系列的完整源代码可以在GitHub repo找到,其中包括所有样式和代码示例。

如果您在任何时候感到困难,还有其他问题,请随时通过以下方式与我们联系: