Рубрики
Без рубрики

Обработка асинхронной природы Node.js: образец проекта

Node.js построен на верхней части двигателя V8 Google, который в поворотах компилирует JavaScript. JavaScript асинхронный по своей природе. Asynchronous – это шаблон программирования, который обеспечивает функцию не блокирующего кода I.e не останавливаться или не зависит от другой функции / процесса для выполнения определенной линии кода.

Автор оригинала: Shahid Shaikh.

Node.js построен на верхней части двигателя V8 Google, который в поворотах компилирует JavaScript. Как многие из вас уже знают, JavaScript асинхронный по своей природе. Asynchronous – это шаблон программирования, который обеспечивает функцию не блокирующего кода I.e не останавливаться или не зависит от другой функции/процесса для выполнения определенной линии кода.

Асинхронный великолепен с точки зрения производительности, утилизации ресурсов и пропускной способности. Но есть некоторые недостатки:

  1. Очень сложно для устаревшего программиста, который будет продолжать async.
  2. Обработка поток управления действительно болезненным.
  3. Обратные вызовы грязные.

Если вы, ориентированный на функционал программист, то вам было бы мало трудно понять асинхронное программирование. Однако, если вы знакомы с многопоточным в Java, то это похоже на это.

Node.js использует ECMAScript в качестве основного языка, поэтому он принимает каждый аспект генераторов, похожего на ECMASSPSTICT, волокна, асинхронный характер кода и т. Д. Рассмотреть следующий код, который заблокирован в природе.

var fs = require("fs");
fs.readFileSync('abc.txt',function(err,data){
  if(!err) {
    console.log(data);
  }
});
console.log("something else");

Теперь рассмотрим следующий асинхронный код:

var fs = require("fs");
fs.readFile('abc.txt',function(err,data){
    if(!err) {
     console.log(data);
    }
});
console.log("something else");

Какая разница?

В первом модуле программа ждала при чтении файла. Он не пойдет дальше до завершения операции чтения, что является примером блокирующего кода. Но в идеале мы должны продолжить дальше, пока программа читала файл, и как только это сделано, мы должны вернуться и обработать это. Это то, что происходит во втором коде.

Во втором коде программа не ждет, поэтому вы видите консоль первого и содержимого файла позже. Однако контроль потока такого рода программы будет стоить вам немного больше времени и работы. Прежде чем двигаться дальше, спросите себя: как вы узнаете, было ли чтение файлов было сделано?

Есть много способов сделать это, но один из популярных способов использует обратный вызов, который похож на систему уведомлений в асинхронном программировании. Как подразумевает имя, это уведомит вас, когда задача ASYNC завершена. Но подожди, мы еще не решили головоломку!

Наличие обратных вызовов в вашем коде не означает, что у вас есть контроль над асинхронной природой JavaScript. Большинство программистов делают эту ошибку и попадают в обратном вызове ад.

Обратный ада:

обратный ад

Наличие ряд обратных вызовов после обратных вызовов известно как «обратный ад» в зоне JavaScript. В этом примере один обратный вызов останавливает выполнение кода, ждет данных, а затем передает его к следующей функции, которая снова имеет обратные вызовы и помещает петли событий в подвесное состояние до завершения обработки, и так далее.

Это выглядит что-то подобное:

function readFile(filename,callback) {
  fs.readFile(filename,function(err,data)
    if(!err) {
      processData(data,function(res)) {
        printData(res);
      }
    }
  });
}

Почему не приятно иметь несколько обратных вызовов?

При использовании обратных вызовов вы в конечном итоге вы можете остановить поток выполнения всей всей программы. Наличие меньшего количества обратных вызовов – это не проблема, но если у вас слишком много обратных вызовов, ваша программа будет в состоянии ожидания, чем исполняющее состояние. Вы действительно не хотите сделать это, потому что, как сказал Google, «не представляйте этого, если это не быстро».

Какое решение?

Чтобы избежать обратного вызова ада, вам необходимо понять дизайн, поток программы таким образом, чтобы вы программировали, используемые ресурсами и быстро работают. Node.js имеет много модулей для контроля потока программы, а один из самых популярных из них Async.js Отказ

Прежде чем идти до async.js, давайте немного обсудим о прототипировании в Node.js. Как вы узнаете, объектно-ориентированные функции доступны в JavaScript с использованием Prototype Design Pattern. Схема дизайна прототипа также называется механизмом «скрытого класса».

В прототипировании мы создаем классы и функции внутри класса и создали его, используя объекты, как мы делаем в C ++ или Java, но самое большое значение состоит в том, что в JavaScript все это объект.

Введение в Async.js.

Async – это коммунальный модуль, который обеспечивает прямые, мощные функции для работы с асинхронным JavaScript. Функции классифицируются в коллекции и контролируют поток вместе с Utils.

async.map(['file1','file2','file3'], fs.stat, function(err, results){
    // results is now an array of stats for each file
});

async.filter(['file1','file2','file3'], fs.exists, function(results){
    // results now equals an array of the existing files
});

async.parallel([
    function(){ ... },
    function(){ ... }
], callback);

async.series([
    function(){ ... },
    function(){ ... }
]);

Используя Async.js, вы можете очень легко и эффективно разрабатывать параллельную/серию/пакетный поток. Я буду разработать программу, чтобы продемонстрировать же.

Пример проекта:

Мы собираемся разработать dumper баз данных. Database Dumper – это программа, которую ребята ETL используют для размещения много данных в базе данных для программистов приложений. На нашей сцене, поскольку у нас нет никакой продукции ETL-проекта, мы постараемся выбросить одну таблицу, у которой много данных фильма.

Откуда мы можем получить данные фильмов?

Вы все слышали о OMDB , самая большая коллекция фильмов все время. Ну, есть одна услуга под названием OMDBAPI, которая предоставляет API для получения информации о фильме в формате JSON. Это то, что нам нужно.

Поток управления:

Наш контрольный поток будет таким:

  1. Получите имя фильма из файла.
  2. Вызовите OMDB, чтобы получить информацию о фильме.
  3. Если найдено, дамп в базе данных.
  4. Если нет, то перейдите к следующему фильму и повторите с шага 1.

Для этого мы собираемся использовать Asyncasterpall () контролировать поток.

Фильмы имена?

Я скомпилировал и поставил имя 3000 фильмов в файле JSON STRUCKING для вас! Да, вы можете получить это от Github тоже.

Это похоже на этот формат:

[  
  {  
    "name":"The 40-Year-Old Virgin"
  },
...
]

Дизайн базы данных.

Создайте базу данных с именем «Фильмографические файлы» и запустите этот запрос внутри вашего сечения SQL.

CREATE TABLE `MoviesData`.`movie` 
(
  `id` INT NOT NULL AUTO_INCREMENT ,
  `Name` VARCHAR(50) NOT NULL ,
  `ReleaseDate` VARCHAR(20) NOT NULL , 
  `Year` VARCHAR(10) NOT NULL , 
  `Cast` VARCHAR(50) NOT NULL , 
  `Plot` VARCHAR(50) NOT NULL , 
  `Genre` VARCHAR(50) NOT NULL , 
  `Rated` VARCHAR(20) NOT NULL , 
  `RunTime` VARCHAR(20) NOT NULL , 
  `Poster` VARCHAR(20) NOT NULL , 
  `Country` VARCHAR(20) NOT NULL , 
  `Language` VARCHAR(20) NOT NULL , 
  `Type` VARCHAR(20) NOT NULL ,
  PRIMARY KEY (`id`)
)
ENGINE = InnoDB;

Убедитесь, что эта таблица создана.

Package.json.

{
  "name": "sadique",
  "version": "0.0.1",
  "dependencies": {
    "async": "~0.9.0",
    "mysql": "^2.7.0"
  }
}

Установка зависимостей, используемых запуском

npm install

команда.

Server.js.

var async = require("async");
var http = require("http");
var movies = require("./inputJSON.json");
var mysql = require("mysql");
var movieArray = [];
var pool;
function processDB() {
  var self = this;
    pool = mysql.createPool({
      connectionLimit : 100,
      host          : 'localhost',
      user          : 'root',
      password : '',
      database  : 'MoviesData',
      debug       :  false
    });
    self.collectMovies();
}
processDB.prototype.collectMovies = function() {
  var self = this;
  for(var i=0;i < movies.length;i++) {
    movieArray.push(movies[i].name);
  }
  async.eachSeries(movieArray,self.processMovie,function(){
    console.log("I am done");
  });
}
processDB.prototype.processMovie = function(movieName,callback) {
  var self = this;
  async.waterfall([
  function(callback) {
    var response = "";
    movieName = movieName.split(' ').join('+');
    http.get("http://www.omdbapi.com/?t="+movieName+"&y=&plot=short&r=json",function(res){
      res.on('data',function(chunk){
      response += chunk;
      });
      res.on('end',function(){
        if(typeof response === "string") {
          response = JSON.parse(response);
    if(response.Response === 'False') {
            console.log("Movie not found");
            callback(true);
    } else {
      callback(null,response,movieName);
      }
  } else {
          callback(true);
          }
      });
      res.on('error',function(){
        console.log("Some error i think");
        callback(true);
      });
    });
  },
  function(MovieResponse,Movie,callback) {
    var SQLquery = 'INSERT into ?? (??,??,??,??,??,??,??,??,??,??,??,??) VALUES '
+ '(?,?,?,?,?,?,?,?,?,?,?,?)';
    var inserts  = ["movie","Name","ReleaseDate","Year","Cast","Plot","Genre","Rated","RunTime","Poster","Country","Language","Type",MovieResponse.Title,MovieResponse.Released,MovieResponse.Year,MovieResponse.Actors,MovieResponse.Plot,MovieResponse.Genre,MovieResponse.imdbRating,MovieResponse.Runtime,MovieResponse.Poster,MovieResponse.Country,MovieResponse.Language,MovieResponse.Type];
    SQLquery = mysql.format(SQLquery,inserts);

    pool.getConnection(function(err,connection){
      if(err) {
        self.stop(err);
        return;
      } else {
          connection.query(SQLquery,function(err,rows){
            connection.release();
            if(err) {
              console.error('error running query', err);
            } else {
             console.log("Inserted rows in DB");
            }
          });
        callback();
  }
      });
}],function(){
      callback();
});
}
processDB.prototype.stop = function(err) {
    console.log("ISSUE WITH MYSQL \n" + err);
    process.exit(1);
}
new processDB();

Запуск программы

Давайте запустим код. Откройте свой терминал, переключитесь в каталог проекта и запустите

node Server.js

Для запуска программы.

Поскольку мы работаем в серии, поэтому для 3000 фильмов потребуется около 7-8 минут, чтобы сбросить базу данных.

Дамп база данных

Если вы хотите попробовать и запустить это параллельно, то API OMDB заблокирует ваш IP, просто чтобы избежать атаки DOS из-за получения много HTTP-запросов на одном временном метеру. Вот скриншот, я попробовал это

OMDB API

Вот как это будет работать последовательно. Он выберет имя фильма из файла один за раз, и позвоните в ПроцессMovie функция. Эта функция позвонит на API OMDB, а затем втолкнул его в свою БД и дает обратный вызов Callee, чтобы обеспечить следующее имя фильма.

Тот же процесс будет повторяться, пока не достигнет конца файла.

В сценарии, где вы получите ошибку, такую как «фильм, не найденный в OMDB» или «Ответ», является пустой или нулевой программой «, программа просто пропустит это имя фильма и не добавит это в базу данных.

Объяснение кода

Чтобы понять код, я разделил его в модули и использовал прототип для структурирования программы.

Наш главный класс – ProcessDB () , который также является скрытым классом, в этом классе мы создадим бассейн MySQL и позвоните в следующую функцию.

В Collectmovies () Функция, мы будем читать имя фильма из файла и хранить их в массиве, который не находится в формате объекта.

Мы используем async.eachseries () Сбор и передача всего массива в нее эта функция достаточно умна, чтобы выбрать один данные из массива вовремя, и мы звоним ProcessMovie () функция. ProcessMovie () это сердце этой программы. Здесь, поскольку у нас есть две операции в руках, мы будем использовать Водопад () коллекция. Что это делает, это предоставляет данные его следующей функции, которая нам нужна.

В asyncasterpall () У нас есть две функции. Первый позвонит API OMDB, а второй добавит информацию в базу данных.

Введите описание изображения здесь

Мы использовали сценарии обработки ошибок в случае неудачи вызова API. В функции SQL мы создаем запрос и призываю MySQL, чтобы сделать это и соответственно предоставляет обратную связь.

Заключение

Async.js – один из популярных и наиболее широко используемых инструментов в сообществе Node.js. Как разработчик Node.js, вы должны знать, как его использовать, так как он наверняка решит большинство ваших проблем и предоставить вам лучшее понимание о обработке асинхронной природы.