Asynchronous programming practice of when. Js under node.js

  • 2020-03-30 04:26:47
  • OfStack

Suppose a business scenario:

With the RSS address, get the RSS and save it in a file. The RSS address is saved in a file.

There are three tasks required to complete the business in this scenario:

1. Read the RSS address from the file.

2. Get RSS.

3. Save to file.

Finally, the three tasks are integrated.

Preparation:

File for RSS address, address.txt.

(link: http://programmer.csdn.net/rss_programmer.html)
 
Task 1:

The contents of the RSS address file are read and returned through a callback.


var getRssAddress = function(path, callback) {
  fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
    callback(err, data);
  });
}

Task 2:

  Get to RSS via RSS address and return error or data via callback.


var getRss = function(url, callback) {
  var data = '';
  http.get(url, function(res) {
    res.on('data', function(chrunk) {
      data += chrunk;
    });
    res.on('end', function() {
      callback(null, data);
    });
  }).on('error', function(err) {
    callback(err, null);
  });
}

 

Task 3:

Save the RSS to a file and return an error via a callback.


var saveRss = function(data, callback) {
  fs.writeFile('rss.txt', data, 'utf8', function(err) {
    callback(err);
  });
}

Integration:


getRssAddress('address.txt', function(err, data) {
  if(err) {
    console.log(err);
    return;
  }
  getRss(data, function(err, data) {
    if(err) {
      console.log(err);
      return;
    }
    saveRss(data, function(err) {
      if(err) console.log(err);
    });
  });
});

The above code is full asynchronous processing, using the most common callback to handle the return of asynchronous logic, the benefits of standard writing, everyone can easily accept; The disadvantage is that the coupling is too strong, it is troublesome to handle exceptions, and the code is not intuitive, especially when the business logic is complex and the processing tasks are too many. Layers of callback will make people feel like stars and the code is difficult to maintain.

One of the implementations of the Promise/A specification, when. Js, addresses just such A problem domain.

Let's take a look at the modified code.

Task 1:


var getRssAddress = function(path) {
    var deferred = when.defer();
      fs.readFile(path, {encoding: 'utf8'}, function (err, data) {
        if (err) deferred.reject(err);
        deferred.resolve(data);
      });     return deferred.promise;
}

 
Task 2:


var getRss = function(url) {
  var deferred = when.defer();
    var data = '';
    http.get(url, function(res) {
      res.on('data', function(chrunk) {
        data += chrunk;
      });
      res.on('end', function() {
        deferred.resolve(data);
      });
    }).on('error', function(err) {
      deferred.reject(err);
    });     return deferred.promise;
}

Task 3:


var saveRss = function(data) {
  var deferred = when.defer();
  fs.writeFile('rss.txt', data, 'utf8', function(err) {
    if(err) deferred.reject(err);
    deferred.resolve();
  });   return deferred.promise;
}

 

Integration:


getRssAddress('address.txt')
  .then(getRss)
  .then(saveRss)
  .catch(function(err) {
    console.log(err);
  });

Explanation:

The promise/A specification defines A "Deferred/ promise" model as A "publish/subscriber" model. Events are published with A Deferred object, which can be A resolve event or A rejected event. A Promise object corresponds to a complete or failed subscription.

In Promises/A specification, each mission has three states: the default (pending), complete (fulfilled), failure (rejected).

1. The default state can be transferred to the completed state in one direction. This process is called resolve, and the corresponding method is deferred.resolve(promiseOrValue).

2. The default state can also be transferred to the failed state one-way, this process is called reject, the corresponding method is deferred.reject(reason);

3. By default, deferred. Notify (update) can also announce the execution information of the task, such as the progress of the execution;

4. The transfer of state is one-time. Once the task is transferred from the initial pending state to another state, it will enter the execution process of the next task.

Follow the code above.

Define a deferred object through when. Defer.

Var deferred = the when. Defer ();
Upon successful asynchronous data acquisition, a completion event is published.

Deferred. Resolve (data);
After an asynchronous data acquisition failure, a failed event is published.

Deferred. Reject (err);
And return the Promise object as a subscription.

Return a deferred. Promise;
A subscription is a subscription for completion/failure/notification through the then method of a Promise object.

GetRssAddress (' address. TXT)
  . Then (getRss)
Then there are three parameters, respectively is onFulfilled, onRejected, onProgress

Promise. Then (onFulfilled onRejected, onProgress)
A task is resolve (data), onFulfilled function will be triggered, data as its argument.

If the previous task was rejected (reason), then the onRejected will be triggered and receive the reason.

Any time, onFulfilled and onRejected are only one can be triggered, and triggers only once.

When. Js also provides an extremely convenient way to handle exceptions, then can pass errors, and when multiple tasks are serialized, we can define onRejected only on the last then. You can also catch an exception for any task by calling the catch function after the last then.

So it's pretty straightforward.

The same code at the page code block index 7

Promise brings great convenience to asynchronous programming, allowing us to focus on the implementation of a single task without falling into a pyramid of doom. The above code is only for basic use, and when.


Related articles: