[Full Stack React] Day 15: Introduction to Promise

This article is reproduced from: Mass translation
Translator: iOSDevLog
Links: http://www.zcfy.cc/article/3814
Original: https://www.fullstackreact.com/30-days-of-react/day-15/

Today, we'll look at what we need to know to learn about Promises at a high level, so we can use this very useful concept to build our applications.

Yesterday We installed the fetch library into our create-react-app project and we started Day 12 Today, we will pick up the concepts and Promises Art.

Promise

As defined by mozilla, committed objects are used to handle asynchronous calculations, and there are some important guarantees that callback methods are difficult to handle (older methods of handling asynchronous code).

A Promise object is simply a wrapper around a value that may or may not be known when instantiating the object and provides a way to post-process the value that is known (also known as resolved) or unavailable for failure (we call rejected here).

The use of the Commitment object gives us the opportunity to associate the ultimate success or failure of an asynchronous operation with functionality for any reason.It also allows us to use code similar to synchronization to handle these complex scenarios.

For example, considering the following synchronization code, we print out the current time in the javascript console:

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

This is fairly straightforward and represents when the browser knows as a new Date() object.Now consider using different clocks on other remote machines.For example, if we're making a happy New Year's clock, it would be great to be able to synchronize users'browsers with others using a single time value for everyone, so no one misses the ball-dropping ceremony.

Suppose we have a way to handle getCurrentTime() clocks that get the current time from a remote server.Now, we'll use setTimeout() to represent this, which returns the time (just like making a request for a slow 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);

Our console.log() log value will return the timeout handler id, which is definitely not the current time.Traditionally, callbacks are used to update code so that it can be called when time is available:

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

What if there were any other errors?How do we capture errors and define retry or error status?

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

Now, what if we want to make a request based on the value of the first request?As a short example, let's reuse the getCurrentTime() function again (as if it were the second method, but allow us to avoid adding another complex function):

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

Handling asynchronous in this way can quickly become complex.In addition, we can get values from previous function calls if we only want one.. There are a lot of tricky situations to deal with when dealing with values that were not present at the time the application was started.

Enter Promise

Using commitment, on the other hand, helps us avoid many of these complications (although not a silver bullet solution, see The Myth of Man and Moon).Previous code, which could be called spaghetti code, can be turned into a cleaner, more synchronized, prospective version:

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

Previous source code examples cleaned up and cleaned up what was happening, avoiding a lot of tricky error handling/capture.

For a successful value, we will use the then () function on the Promise instance object.The then() function is called, regardless of whether the return value is Promise itself.For example, in the example above, the getCurrentTime() function resolves to the current Time() value (upon successful completion), calls the then() function on the return value (which is another promise), and so on.

To catch errors anywhere in the commitment chain, we can use the catch() method.

In the example above, we use a chain of commitments to create a chain of actions, called one by one.
The commitment chain sounds complex, but it's basically simple.Essentially, we can call multiple asynchronous operations "synchronously" in succession.Each call to then() is called with the return value of the previous then() function.
For example, if we want to manipulate the value of a getCurrentTime() call, we can add a link to the chain as follows:

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

Use Guarantee alone

Commitments should only be in one of three states at any given time:

  • undetermined
  • Completed (resolved)
  • Rejected (Error)

A pending commitment can only result in a satisfying state or a rejected state once and only once, which can avoid some fairly complex error scenarios.This means that we can only return one promise once.If we want to rerun a function that uses the promise, we need to create a new one.

Create a Promise

We can use the Promise constructor to create new commitments (as shown in the example above).It accepts a function that has two parameters to run:

  • The onSuccess (or resolve) function will be called after a successful resolution
  • The onFail (or reject) function is called after a failed rejection

Looking back at our function above, we can see that if the request succeeds, we call the resolve() function, and if the method returns an error condition, we call the reject() function.

var promise = new Promise(function(resolve, reject) {
  // call resolve if the method succeeds
  resolve(true);
})
promise.then(bool => console.log('Bool is true'))

Now that we know what commitments are, how to use them, and how to create them, we can actually use the fetch() library that was installed yesterday.

Keywords: Javascript React

Added by mattkenefick on Fri, 07 Jun 2019 20:28:49 +0300