One place for hosting & domains

      Nodejs

      Cara Menginstal Node.js pada Ubuntu 20.04


      Pengantar

      Node.js adalah suatu runtime JavaScript untuk pemrograman sisi server. Ini memungkinkan pengembang untuk menciptakan fungsionalitas backend yang dapat diskalakan dengan menggunakan JavaScript, suatu bahasa yang banyak orang sudah akrab dengannya dari pengembangan web berbasis peramban.

      Dalam panduan ini, kami akan menunjukkan kepada Anda tiga cara menginstal Node.js pada server Ubuntu 20.04:

      • menggunakan apt untuk menginstal paket nodejs dari repositori perangkat lunak asali Ubuntu
      • menggunakan apt dengan repositori perangkat lunak PPA alternatif untuk menginstal versi spesifik paket nodejs
      • menginstal nvm, Node Version Manager, dan menggunakannya untuk menginstal dan mengelola beberapa versi Node.js

      Bagi banyak pengguna, menggunakan apt dengan repo asali sudah mencukupi. Jika Anda memerlukan versi spesifik yang lebih baru (atau warisan) dari Node, Anda harus menggunakan repositori PPA. Jika Anda secara aktif mengembangkan aplikasi Node dan perlu sering beralih di antara beberapa versi node, pilihlah metode nvm.

      Prasyarat

      Panduan ini mengasumsikan bahwa Anda menggunakan Ubuntu 20.04. Sebelum Anda memulai, Anda harus memiliki akun pengguna non-root dengan privilese sudo yang disiapkan pada sistem Anda. Anda dapat belajar cara melakukan ini dengan mengikuti tutorial penyiapan server awal untuk Ubuntu 20.04.

      Opsi 1 — Menginstal Node.js dengan Apt dari Repositori Asali

      Ubuntu 20.04 berisi versi Node.js di dalam repositori asalinya, yang dapat digunakan untuk memberi pengalaman yang konsisten pada banyak sistem. Pada saat dokumen ini ditulis, versi di dalam repositori adalah 10.19. Ini bukanlah versi terbaru, namun versi ini seharusnya stabil dan mencukupi untuk eksperimen cepat dengan bahasa ini.

      Untuk mendapatkan versi ini, Anda dapat menggunakan manajer paket apt. Segarkan indeks paket lokal Anda terlebih dahulu dengan mengetik:

      Lalu instal Node.js:

      Periksa bahwa instalasi telah berhasil dengan bertanya kepada node terkait nomor versinya:

      Output

      v10.19.0

      Jika paket di dalam repositori sesuai dengan kebutuhan Anda, itu adalah semua yang Anda perlukan untuk menyiapkan Node.js. Pada sebagian besar kasus, Anda juga perlu menginstal npm, manajer paket Node.js. Anda dapat melakukan ini dengan menginstal paket npm dengan apt:

      Ini akan memungkinkan Anda untuk menginstal modul dan paket untuk digunakan dengan Node.js.

      Pada titik ini, Anda telah berhasil menginstal Node.js dan npm dengan menggunakan apt dan repositori perangkat lunak Ubuntu asali. Bagian berikutnya akan menunjukkan cara menggunakan suatu repositori alternatif untuk menginstal versi Node.js yang berbeda.

      Opsi 2 — Menginstal Node.js dengan Apt Menggunakan NodeSource PPA

      Untuk menginstal versi Node.js yang berbeda, Anda dapat menggunakan suatu PPA (personal package archive/arsip paket pribadi) yang dikelola oleh NodeSource. PPA ini menyediakan lebih banyak versi Node.js daripada repositori Ubuntu resmi. Node.js v10, v12, v13, dan v14 tersedia saat dokumen ini ditulis.

      Pertama, kita akan menginstal PPA untuk mendapatkan akses ke paket-paketnya. Dari direktori rumah Anda, gunakan curl untuk mengambil skrip instalasi untuk versi yang lebih Anda sukai, pastikan untuk mengganti 14.x dengan string versi yang lebih Anda sukai (jika berbeda).

      • cd ~
      • curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh

      Silakan mengacu ke dokumentasi NodeSource untuk informasi lebih lanjut tentang versi yang tersedia.

      Periksa isi skrip yang sudah diunduh dengan nano (atau editor teks yang lebih Anda sukai):

      Jika Anda yakin bahwa skrip aman untuk dijalankan, keluarlah dari editor Anda, lalu jalankan skrip dengan sudo:

      • sudo bash nodesource_setup.sh

      PPA akan ditambahkan ke konfigurasi Anda dan cache paket lokal Anda akan diperbarui secara otomatis. Anda sekarang dapat menginstal paket Node.js dengan cara yang sama seperti yang Anda lakukan di bagian sebelumnya:

      Lakukan verifikasi bahwa Anda telah menginstal versi baru dengan menjalankan node dengan bendera versi -v:

      Output

      v14.2.0

      Paket nodejs NodeSource berisi baik biner node dan npm, sehingga Anda tidak perlu menginstal npm secara terpisah.

      Pada titik ini, Anda telah berhasil menginstal Node.js dan npm dengan menggunakan apt dan NodeSource PPA. Bagian berikutnya akan menunjukkan cara menggunakan Node Version Manager untuk menginstal dan mengelola beberapa versi Node.js.

      Opsi 3 — Menginstal Node Menggunakan Node Version Manager

      Cara lain untuk menginstal Node.js yang sangat fleksibel adalah dengan menggunakan nvm, Node Version Manager. Perangkat lunak ini memungkinkan Anda untuk menginstal dan mengelola banyak versi independen Node.js yang berbeda, dan paket Node yang terkait, pada saat bersamaan.

      Untuk menginstal NVM pada mesin Ubuntu 20.04 Anda, kunjungi laman GitHub proyek ini. Salin perintah curl dari berkas README yang ditampilkan pada halaman utama. Ini akan memberi tahu Anda versi terbaru dari skrip instalasi.

      Sebelum menyalurkan perintah melalui bash, Anda selalu disarankan untuk mengaudit skrip untuk memastikan bahwa skrip tersebut tidak melakukan apa pun yang tidak Anda setujui. Anda dapat melakukan itu dengan menghapus segmen | bash di akhir perintah curl:

      • curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh

      Perhatikan dan pastikan Anda nyaman dengan perubahan yang dibuat. Ketika Anda puas, jalankan perintah lagi dengan menambahkan | bash di bagian akhir. URL yang Anda gunakan akan berubah tergantung versi terbaru nvm, tetapi untuk saat ini, skrip dapat diunduh dan dieksekusi dengan mengetik:

      • curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

      Ini akan menginstal skrip nvm ke akun pengguna Anda. Untuk menggunakannya, pertama-tama Anda harus mencari berkas .bashrc:

      Sekarang, Anda dapat bertanya pada NVM tentang versi Node yang tersedia:

      Output

      . . . v12.13.0 (LTS: Erbium) v12.13.1 (LTS: Erbium) v12.14.0 (LTS: Erbium) v12.14.1 (LTS: Erbium) v12.15.0 (LTS: Erbium) v12.16.0 (LTS: Erbium) v12.16.1 (LTS: Erbium) v12.16.2 (LTS: Erbium) v12.16.3 (Latest LTS: Erbium) v13.0.0 v13.0.1 v13.1.0 v13.2.0 v13.3.0 v13.4.0 v13.5.0 v13.6.0 v13.7.0 v13.8.0 v13.9.0 v13.10.0 v13.10.1 v13.11.0 v13.12.0 v13.13.0 v13.14.0 v14.0.0 v14.1.0 v14.2.0

      Daftarnya sangat panjang! Anda dapat menginstal versi Node dengan mengetik salah satu versi rilis yang Anda lihat. Misalnya, untuk mendapatkan versi v13.6.0, Anda dapat mengetik:

      Anda dapat melihat versi lain yang telah Anda instal dengan mengetik:

      nvm list
      

      Output

      -> v13.6.0 default -> v13.6.0 node -> stable (-> v13.6.0) (default) stable -> 13.6 (-> v13.6.0) (default) . . .

      Ini menampilkan versi yang aktif saat ini pada baris pertama (-> v13.6.0), yang diikuti oleh beberapa nama alias dan versi yang ditunjukkan oleh nama alias itu.

      Catatan: jika Anda juga memiliki versi Node.js yang diinstal melalui apt, Anda mungkin akan melihat entri system di sini. Anda selalu dapat mengaktifkan versi Node yang diinstal sistem dengan menggunakan nvm use system.

      Sebagai tambahan, Anda akan melihat nama alias untuk berbagai rilis dukungan jangka panjang (atau LTS) dari Node:

      Output

      . . . lts/* -> lts/erbium (-> N/A) lts/argon -> v4.9.1 (-> N/A) lts/boron -> v6.17.1 (-> N/A) lts/carbon -> v8.17.0 (-> N/A) lts/dubnium -> v10.20.1 (-> N/A) lts/erbium -> v12.16.3 (-> N/A)

      Kita dapat menginstal rilis berdasarkan nama alias ini juga. Misalnya, untuk menginstal versi dukungan jangka panjang terbaru, erbium, jalankan yang berikut ini:

      Output

      Downloading and installing node v12.16.3... . . . Now using node v12.16.3 (npm v6.14.4)

      Anda dapat beralih di antara versi yang terinstal dengan nvm use:

      nvm use v13.6.0
      
      Now using node v13.6.0 (npm v6.13.4)
      

      Anda dapat memverifikasi bahwa instalasi berhasil dengan menggunakan teknik yang sama dari bagian lain, dengan mengetik:

      Output

      v13.6.0

      Versi Node yang benar terinstal pada mesin kita seperti yang kita harapkan. Versi npm yang kompatibel juga tersedia.

      Kesimpulan

      Ada beberapa cara untuk mengaktifkan dan menjalankan Node.js pada server Ubuntu 20.04 Anda. Keadaan Anda akan menentukan metode mana yang terbaik untuk kebutuhan Anda. Walaupun menggunakan versi yang dikemas di dalam repositori Ubuntu adalah metode termudah, namun menggunakan nvm atau NodeSource PPA menawarkan fleksibilitas tambahan.

      Untuk informasi lebih lanjut tentang pemrograman dengan Node.js, silakan merujuk ke seri tutorial kami Cara Melakukan Pengodean di Node.js.



      Source link

      How To Create an HTTP Client with Core HTTP in Node.js


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      It’s common for a modern web application to communicate with other servers to accomplish a task. For example, a web app that allows you to purchase a book online may involve communication between a customer orders server, a book inventory server, and a payment server. In this design, the different services communicate via web APIs—standard formats that allow you to programmatically send and receive data. In a Node.js app, you can communicate with web APIs by making HTTP requests.

      Node.js comes bundled with an http and an https module. These modules have functions to create an HTTP server so that a Node.js program can respond to HTTP requests. They can also make HTTP requests to other servers. This key functionality equips Node.js programmers to create modern, API-driven web applications with Node.js. As it’s a core module, you do not need to install any libraries to use it.

      In this tutorial, you will use the https module to make HTTP requests to JSON Placeholder, a fake REST API for testing purposes. You will begin by making a GET request, the standard HTTP request to receive data. You will then look at ways to customize your request, such as by adding headers. Finally, you will make POST, PUT, and DELETE requests so that you can modify data in an external server.

      Prerequisites

      • This tutorial requires that you have Node.js installed. Once installed, you will be able to access the https module that’s used throughout the tutorial. This tutorial uses Node.js version 10.19.0. To install Node.js on macOS or Ubuntu 18.04, follow the steps in How To Install Node.js and Create a Local Development Environment on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.

      • The methods used to send HTTP requests have a Stream-based API. In Node.js, streams are instances of event emitters. The way in which you respond to data coming from a stream is the same as the way in which you respond to data from events. If you are curious, you can get more in-depth knowledge of event emitters by reading our Using Event Emitters in Node.js guide.

      Step 1 — Making a GET Request

      When you interact with an API, you typically make GET requests to retrieve data from web servers. In this step, you’ll look at two functions to make GET requests in Node.js. Your code will retrieve a JSON array of user profiles from a publicly accessible API.

      The https module has two functions to make GET requests—the get() function, which can only make GET requests, and the request() function, which makes other types of requests. You will begin by making a request with the get() function.

      Making Requests with get()

      HTTP requests using the get() function have this format:

      https.get(URL_String, Callback_Function) {
          Action
      }
      

      The first argument is a string with the endpoint you’re making the request to. The second argument is a callback function, which you use to handle the response.

      First, set up your coding environment. In your terminal, create a folder to store all your Node.js modules for this guide:

      Enter that folder:

      Create and open a new file in a text editor. This tutorial will use nano as it’s available in the terminal:

      • nano getRequestWithGet.js

      To make HTTP requests in Node.js, import the https module by adding the follow line:

      requests/getRequestWithGet.js

      const https = require('https');
      

      Note:: Node.js has an http and an https module. They have the same functions and behave in a similar manner, but https makes the requests through the Transport Layer Security (TLS/SSL). As the web servers you are using are available via HTTPS, you will use the https module. If you are making requests to and from URLs that only have HTTP, then you would use the http module.

      Now use the http object to make a GET request to the API to retrieve a list of users. You will use JSON Placeholder, a publicly available API for testing. This API does not keep a record of any changes you make in your requests. It simulates a real server, and returns mocked responses as long as you send a valid request.

      Write the following highlighted code in your text editor:

      requests/getRequestWithGet.js

      const https = require('https');
      
      let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => { });
      

      As mentioned in the function signature, the get() function takes two parameters. The first is the API URL you are making the request to in string format and the second is a callback to handle the HTTP response. To read the data from your response, you have to add some code in the callback.

      HTTP responses come with a status code. A status code is a number that indicates how successful the response was. Status codes between 200 and 299 are positive responses, while codes between 400 and 599 are errors. You can learn more about status codes in our How To Troubleshoot Common HTTP Error Codes guide.

      For this request, a successful response would have a 200 status code. The first thing you’ll do in your callback will be to verify that the status code is what you expect. Add the following code to the callback function:

      requests/getRequestWithGet.js

      const https = require('https');
      
      let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
        if (res.statusCode !== 200) {
          console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      });
      

      The response object that’s available in the callback has a statusCode property that stores the status code. If the status code is not 200, you log an error to the console and exit.

      Note the line that has res.resume(). You included that line to improve performance. When making HTTP requests, Node.js will consume all the data that’s sent with the request. The res.resume() method tells Node.js to ignore the stream’s data. In turn, Node.js would typically discard the data more quickly than if it left it for garbage collection—a periodic process that frees an application’s memory.

      Now that you’ve captured error responses, add code to read the data. Node.js responses stream their data in chunks. The strategy for retrieving data will be to listen for when data comes from the response, collate all the chunks, and then parse the JSON so your application can use it.

      Modify the request callback to include this code:

      requests/getRequestWithGet.js

      const https = require('https');
      
      let request = https.get('https://jsonplaceholder.typicode.com/users?_limit=2', (res) => {
        if (res.statusCode !== 200) {
          console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      
        let data="";
      
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Retrieved all data');
          console.log(JSON.parse(data));
        });
      });
      

      You begin by creating a new variable data that’s an empty string. You can store data as an array of numbers representing byte data or a string. This tutorial uses the latter as it’s easier to convert a JSON string to a JavaScript object.

      After creating the data variable, you create an event listener. Node.js streams the data of an HTTP response in chunks. Therefore, when the response object emits a data event, you will take the data it received and add it to your data variable.

      When all the data from the server is received, Node.js emits a close event. At this point, you parse the JSON string stored in data and log the result to the console.

      Your Node.js module can now communicate with the JSON API and log the list of users, which will be a JSON array of three users. However, there’s one small improvement you can make first.

      This script will throw an error if you are unable to make a request. You may not be able to make a request if you lose your internet connection, for example. Add the following code to capture errors when you’re unable to send an HTTP request:

      requests/getRequestWithGet.js

      ...
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Retrieved all data');
          console.log(JSON.parse(data));
        });
      
      });
      
      request.on('error', (err) => {
        console.error(`Encountered an error trying to make a request: ${err.message}`);
      });
      

      When a request is made but cannot be sent, the request object emits an error event. If an error event is emitted but not listened to, the Node.js program crashes. Therefore, to capture errors you add an event listener with the on() function and listen for error events. When you get an error, you log its message.

      That’s all the code for this file. Save and exit nano by pressing CTRL+X.

      Now execute this program with node:

      • node getRequestWithGet.js

      Your console will display this response:

      Output

      Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: 'Sincere@april.biz', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: 'Shanna@melissa.tv', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

      This means you’ve successfully made a GET request with the core Node.js library.

      The get() method you used is a convenient method Node.js provides because GET requests are a very common type of request. Node.js provides a request() method to make a request of any type. Next, this tutorial will examine how to make a GET request with request().

      Making Requests with request()

      The request() method supports multiple function signatures. You’ll use this one for the subsequent example:

      https.request(URL_String, Options_Object, Callback_Function) {
          Action
      }
      

      The first argument is a string with the API endpoint. The second argument is a JavaScript object containing all the options for the request. The last argument is a callback function to handle the response.

      Create a new file for a new module called getRequestWithRequest.js:

      • nano getRequestWithRequest.js

      The code you will write is similar to the getRequestWithGet.js module you wrote earlier. First, import the https module:

      requests/getRequestWithRequest.js

      const https = require('https');
      

      Next, create a new JavaScript object that contains a method key:

      requests/getRequestWithRequest.js

      const https = require('https');
      
      const options = {
        method: 'GET'
      };
      

      The method key in this object will tell the request() function what HTTP method the request is using.

      Next, make the request in your code. The following codeblock highlights code that was different from the request made with the get() method. In your editor, enter all of the following lines:

      requests/getRequestWithRequest.js

      ...
      
      let request = https.request('https://jsonplaceholder.typicode.com/users?_limit=2', options, (res) => {
        if (res.statusCode !== 200) {
          console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      
        let data="";
      
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Retrieved all data');
          console.log(JSON.parse(data));
        });
      });
      
      request.end();
      
      request.on('error', (err) => {
        console.error(`Encountered an error trying to make a request: ${err.message}`);
      });
      

      To make a request using request(), you provide the URL in the first argument, an object with the HTTP options in the second argument, and a callback to handle the response in the third argument.

      The options variable you created earlier is the second argument, telling Node.js that this is a GET request. The callback is unchanged from when you first wrote it.

      You also call the end() method of the request variable. This is an important method that must be called when using the request() function. It completes the request, allowing it to be sent. If you don’t call it, the program will never complete, as Node.js will think you still have data to add to the request.

      Save and exit nano with CTRL+X, or the equivalent with your text editor.

      Run this program in your terminal:

      • node getRequestWithRequest.js

      You will receive this output, which is the same as the first module:

      Output

      Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: 'Sincere@april.biz', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: 'Shanna@melissa.tv', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

      You have now used the request() method to make a GET request. It’s important to know this function as it allows you to customize your request in ways the get() method cannot, like making requests with other HTTP methods.

      Next, you will configure and customize your requests with the request() function.

      Step 2 — Configuring HTTP request() Options

      The request() function allows you to send HTTP requests without specifying the URL in the first argument. In this case, the URL would be contained with the options object, and the request() would have this function signature:

      https.request(Options_Object, Callback_Function) {
          Action
      }
      

      In this step, you will use this functionality to configure your request() with the options object.

      Node.js allows you to enter the URL in the options object you pass to the request. To try this out, reopen the getRequestWithRequest.js file:

      • nano getRequestWithRequest.js

      Remove the URL from the request() call so that the only arguments are the options variable and the callback function:

      requests/getRequestWithRequest.js

      const https = require('https');
      
      const options = {
        method: 'GET',
      };
      
      let request = https.request(options, (res) => {
      ...
      

      Now add the following properties to the options object:

      requests/getRequestWithRequest.js

      const https = require('https');
      
      const options = {
        host: 'jsonplaceholder.typicode.com',
        path: '/users?_limit=2',
        method: 'GET'
      };
      
      let request = https.request(options, (res) => {
      ...
      

      Instead of one string URL, you have two properties—host and path. The host is the domain name or IP address of the server you’re accessing. The path is everything that comes after the domain name, including query parameters (values after the question mark).

      The options object can hold other useful data that goes into a request. For example, you can provide request headers in the options. Headers typically send metadata about the request.

      When developers create APIs, they may choose to support different data formats. One API endpoint may be able to return data in JSON, CSV, or XML. In those APIs, the server may look at the Accept header to determine the correct response type.

      The Accept header specifies the type of data the user can handle. While the API being used in these examples only return JSON, you can add the Accept header to your request to explicitly state that you want JSON.

      Add the following lines of code to append the Accept header:

      requests/getRequestWithRequest.js

      const https = require('https');
      
      const options = {
        host: 'jsonplaceholder.typicode.com',
        path: '/users?_limit=2',
        method: 'GET',
        headers: {
          'Accept': 'application/json'
        }
      };
      

      By adding headers, you’ve covered the four most popular options that are sent in Node.js HTTP requests: host, path, method, and headers. Node.js supports many more options; you can read more at the official Node.js docs for more information.

      Enter CTRL+X to save your file and exit nano.

      Next, run your code once more to make the request by only using options:

      • node getRequestWithRequest.js

      The results will be the same as your previous runs:

      Output

      Retrieved all data [ { id: 1, name: 'Leanne Graham', username: 'Bret', email: 'Sincere@april.biz', address: { street: 'Kulas Light', suite: 'Apt. 556', city: 'Gwenborough', zipcode: '92998-3874', geo: [Object] }, phone: '1-770-736-8031 x56442', website: 'hildegard.org', company: { name: 'Romaguera-Crona', catchPhrase: 'Multi-layered client-server neural-net', bs: 'harness real-time e-markets' } }, { id: 2, name: 'Ervin Howell', username: 'Antonette', email: 'Shanna@melissa.tv', address: { street: 'Victor Plains', suite: 'Suite 879', city: 'Wisokyburgh', zipcode: '90566-7771', geo: [Object] }, phone: '010-692-6593 x09125', website: 'anastasia.net', company: { name: 'Deckow-Crist', catchPhrase: 'Proactive didactic contingency', bs: 'synergize scalable supply-chains' } } ]

      As APIs can vary from provider to provider, being comfortable with the options object is key to adapting to their differing requirements, with the data types and headers being some of the most common variations.

      So far, you have only done GET requests to retrieve data. Next, you will make a POST request with Node.js so you can upload data to a server.

      Step 3 — Making a POST Request

      When you upload data to a server or want the server to create data for you, you typically send a POST request. In this section, you’ll create a POST request in Node.js. You will make a request to create a new user in the users API.

      Despite being a different method from GET, you will be able to reuse code from the previous requests when writing your POST request. However, you will have to make the following adjustments:

      • Change the method in the options object to POST
      • Add a header to state you are uploading JSON
      • Check the status code to confirm a user was created
      • Upload the new user’s data

      To make these changes, first create a new file called postRequest.js. Open this file in nano or an alternative text editor:

      Begin by importing the https module and creating an options object:

      requests/postRequest.js

      const https = require('https');
      
      const options = {
        host: 'jsonplaceholder.typicode.com',
        path: '/users',
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json; charset=UTF-8'
        }
      };
      

      You change the path to match what’s required for POST requests. You also updated the method to POST. Lastly, you added a new header in your options Content-Type. This header tells the server what type of data you are uploading. In this case, you’ll be uploading JSON data with UTF-8 encoding.

      Next, make the request with the request() function. This is similar to how you made GET requests, but now you look for a different status code than 200. Add the following lines to the end of your code:

      requests/postRequest.js

      ...
      const request = https.request(options, (res) => {
        if (res.statusCode !== 201) {
          console.error(`Did not get a Created from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      
        let data="";
      
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Added new user');
          console.log(JSON.parse(data));
        });
      });
      

      The highlighted line of code checks if the status code is 201. The 201 status code is used to indicate that the server created a resource.

      This POST request is meant to create a new user. For this API, you need to upload the user details. Create some user data and send that with your POST request:

      requests/postRequest.js

      ...
      
      const requestData = {
        name: 'New User',
        username: 'digitalocean',
        email: 'user@digitalocean.com',
        address: {
          street: 'North Pole',
          city: 'Murmansk',
          zipcode: '12345-6789',
        },
        phone: '555-1212',
        website: 'digitalocean.com',
        company: {
          name: 'DigitalOcean',
          catchPhrase: 'Welcome to the developer cloud',
          bs: 'cloud scale security'
        }
      };
      
      request.write(JSON.stringify(requestData));
      

      You first created the requestData variable, which is a JavaScript object containing user data. Your request does not include an id field, as servers typically generate these while saving the new data.

      You next use the request.write() function, which accepts a string or buffer object to send along with the request. As your requestData variable is an object, you used the JSON.stringify function to convert it to a string.

      To complete this module, end the request and check for errors:

      requests/postRequest.js

      ...
      
      request.end();
      
      request.on('error', (err) => {
        console.error(`Encountered an error trying to make a request: ${err.message}`);
      });
      

      It’s important that you write data before you use the end() function. The end() function tells Node.js that there’s no more data to be added to the request and sends it.

      Save and exit nano by pressing CTRL+X.

      Run this program to confirm that a new user was created:

      The following output will be displayed:

      Output

      Added new user { name: 'New User', username: 'digitalocean', email: 'user@digitalocean.com', address: { street: 'North Pole', city: 'Murmansk', zipcode: '12345-6789' }, phone: '555-1212', website: 'digitalocean.com', company: { name: 'DigitalOcean', catchPhrase: 'Welcome to the developer cloud', bs: 'cloud scale security' }, id: 11 }

      The output confirms that the request was successful. The API returned the user data that was uploaded, along with the ID that was assigned to it.

      Now that you have learned how to make POST requests, you can upload data to servers in Node.js. Next you will try out PUT requests, a method used to update data in a server.

      Step 4 — Making a PUT Request

      Developers make a PUT request to upload data to a server. While this may be similar to POST requests, PUT requests have a different function. PUT requests are idempotent—you can run a PUT request multiple times and it will have the same result.

      In practice, the code you write is similar to that of a POST request. You set up your options, make your request, write the data you want to upload, and verify the response.

      To try this out, you’re going to create a PUT request that updates the first user’s username.

      As the code is similar to the POST request, you’ll use that module as a base for this one. Copy the postRequest.js into a new file, putRequest.js:

      • cp postRequest.js putRequest.js

      Now open putRequest.js in a text editor:

      Make these highlighted changes so that you send a PUT request to https://jsonplaceholder.typicode.com/users/1:

      requests/putRequest.js

      const https = require('https');
      
      const options = {
        host: 'jsonplaceholder.typicode.com',
        path: '/users/1',
        method: 'PUT',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json; charset=UTF-8'
        }
      };
      
      const request = https.request(options, (res) => {
        if (res.statusCode !== 200) {
          console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      
        let data="";
      
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Updated data');
          console.log(JSON.parse(data));
        });
      });
      
      const requestData = {
        username: 'digitalocean'
      };
      
      request.write(JSON.stringify(requestData));
      
      request.end();
      
      request.on('error', (err) => {
        console.error(`Encountered an error trying to make a request: ${err.message}`);
      });
      

      You first change the path and method properties of the options object. path in this case identifies the user that you are going to update. When you make the request, you check if the response code was 200, meaning that the request was OK. The data you are uploading now only contains the property you are updating.

      Save and exit nano with CTRL+X.

      Now execute this Node.js program in your terminal:

      You will receive this output:

      Output

      Updated data { username: 'digitalocean', id: 1 }

      You sent a PUT request to update a pre-existing user.

      So far you have learned how to retrieve, add, and update data. To give us a full command of managing data via APIs, you’ll next make a DELETE request to remove data from a server.

      Step 5 — Making a DELETE Request

      The DELETE request is used to remove data from a server. It can have a request body, but most APIs tend not to require them. This method is used to delete an entire object from the server. In this section, you are going to delete a user using the API.

      The code you will write is similar to that of a GET request, so use that module as a base for this one. Copy the getRequestWithRequest.js file into a new deleteRequest.js file:

      • cp getRequestWithRequest.js deleteRequest.js

      Open deleteRequest.js with nano:

      Now modify the code at the highlighted parts, so you can delete the first user in the API:

      requests/putRequest.js

      const https = require('https');
      
      const options = {
        host: 'jsonplaceholder.typicode.com',
        path: '/users/1',
        method: 'DELETE',
        headers: {
          'Accept': 'application/json',
        }
      };
      
      const request = https.request(options, (res) => {
        if (res.statusCode !== 200) {
          console.error(`Did not get an OK from the server. Code: ${res.statusCode}`);
          res.resume();
          return;
        }
      
        let data="";
      
        res.on('data', (chunk) => {
          data += chunk;
        });
      
        res.on('close', () => {
          console.log('Deleted user');
          console.log(JSON.parse(data));
        });
      });
      
      request.end();
      
      request.on('error', (err) => {
        console.error(`Encountered an error trying to make a request: ${err.message}`);
      });
      

      For this module, you begin by changing the path property of the options object to the resource you want to delete—the first user. You then change the method to DELETE.

      Save and exit this file by pressing CTRL+X.

      Run this module to confirm it works. Enter the following command in your terminal:

      The program will output this:

      Output

      Deleted user {}

      While the API does not return a response body, you still got a 200 response so the request was OK.

      You’ve now learned how to make DELETE requests with Node.js core modules.

      Conclusion

      In this tutorial, you made GET, POST, PUT, and DELETE requests in Node.js. No libraries were installed; these requests were made using the standard https module. While GET requests can be made with a get() function, all other HTTP methods are done via the request() method.

      The code you wrote was written for a publicly available, test API. However, the way you write requests will work for all types of APIs. If you would like to learn more about APIs, check out our API topic page. For more on developing in Node.js, return to the How To Code in Node.js series.



      Source link

      Starten von untergeordneten Prozessen in Node.js


      Der Autor hat den COVID-19 Relief Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Wenn ein Benutzer ein einzelnes Node.js-Programm ausführt, wird es als einzelner Betriebssystem-(OS)-Prozess ausgeführt, der die Instanz des laufenden Programms darstellt. In diesem Prozess führt Node.js Programme auf einem einzigen Thread aus. Wie bereits in dieser Serie im Tutorial So schreiben Sie asynchronen Code in Node.js erwähnt können Operationen, die eine lange Zeit zur Ausführung in JavaScript benötigen, den Node.js-Thread blockieren und die Ausführung anderen Codes verzögern, da nur ein Thread in einem einzelnen Prozess ausgeführt werden kann. Eine Schlüsselstrategie zur Umgehung dieses Problems besteht darin, einen Kindprozess – oder einen durch einen anderen Prozess erstellten Prozess – bei lang laufenden Aufgaben zu starten. Wenn ein neuer Prozess gestartet wird, kann das Betriebssystem Multiprocessing-Techniken einsetzen, um sicherzustellen, dass der hauptsächliche Node.js-Prozess und der zusätzliche Kindprozess gleichzeitig ausgeführt werden.

      Node.js enthält das child_process-Modul, das über Funktionen zur Erstellung neuer Prozesse verfügt. Neben der Bewältigung von langwierigen Aufgaben kann dieses Modul auch eine Schnittstelle mit dem OS bilden und Shell-Befehle ausführen. Systemadministratoren können Node.js zum Ausführen von Shell-Befehlen verwenden, um ihre Operationen als Node.js-Modul anstelle von Shell-Skripten zu strukturieren und zu pflegen.

      In diesem Tutorial erstellen Sie Kindprozesse bei der Ausführung einer Reihe von Node.js-Beispielanwendungen. Sie erstellen Prozesse mit dem child_process-Modul durch Abrufen der Ergebnisse eines Kindprozesses über einen Puffer oder eine Zeichenfolge mit der exec()-Funktion und dann aus einem Datenstream mit der spawn()-Funktion. Abschließend verwenden fork() zur Erstellung eines Kindprozesses eines anderen Node.js-Programms, mit dem Sie während der Ausführung kommunizieren können. Um diese Konzepte zu illustrieren, erstellen Sie ein Programm zur Auflistung des Inhalts eines Verzeichnisses, ein Programm zur Auffindung von Dateien und einen Webserver mit mehreren Endpunkten.

      Voraussetzungen

      Schritt 1 — Erstellen eines Kindprozesses mit exec()

      Entwickler erstellen üblicherweise Kindprozesse zur Ausführung von Befehlen in ihrem Betriebssystem, wenn sie die Ausgabe ihrer Node.js-Programme mit einer Shell manipulieren müssen, so wie zum Beispiel bei der Shell-Weiterleitung oder -Umleitung. Die exec()-Funktion in Node.js erstellt einen neuen Shell-Prozess und führt in dieser Shell einen Befehl aus. Die Ausgabe des Befehls wird in einem Puffer im Arbeitsspeicher aufbewahrt, den Sie über eine in exec() übergebene Callback-Funktion akzeptieren können.

      Beginnen wir mit der Erstellung unserer ersten Kindprozesse in Node.js. Zuerst müssen wir unsere Codierungsumgebung einrichten, um die Skripte, die wir in diesem Tutorial erstellen, zu speichern. Erstellen Sie im Terminal einen Ordner namens child-processes:

      Geben Sie diesen Ordner im Terminal mit dem cd-Befehl ein:

      Erstellen Sie eine neue Datei namens listFiles.js und öffnen Sie die Datei in einem Texteditor. In diesem Tutorial verwenden wir nano, einen Terminaltexteditor.

      Wir schreiben ein Node.js-Modul, das die exec()-Funktion zur Ausführung des ls-Befehls verwendet. Der ls-Befehl listet die Dateien und Ordner in einem Verzeichnis. Dieses Programm nimmt die Ausgabe des ls-Befehls und zeigt sie dem Benutzer an.

      Fügen Sie im Texteditor den folgenden Code hinzu:

      ~/child-processes/listFiles.js

      const { exec } = require('child_process');
      
      exec('ls -lh', (error, stdout, stderr) => {
        if (error) {
          console.error(`error: ${error.message}`);
          return;
        }
      
        if (stderr) {
          console.error(`stderr: ${stderr}`);
          return;
        }
      
        console.log(`stdout:n${stdout}`);
      });
      

      Wir importieren zunächst den exec()-Befehl aus dem child_process-Modul unter Verwendung der JavaScript-Destrukturierung. Nach dem Import verwenden wir die exec()-Funktion. Das erste Argument ist der Befehl, den wir ausführen möchten. In diesem Fall ist es ls -lh, der alle Dateien und Ordner im aktuellen Verzeichnis im Langformat listet, mit einer Gesamtdateigröße in visuell lesbaren Einheiten am Anfang der Ausgabe.

      Das zweite Argument ist eine Callback-Funktion mit drei Parametern: error, stdout und stderr. Wenn die Ausführung des Befehls fehlschlägt, erfasst error den entsprechenden Grund. Das kann vorkommen, wenn die Shell den Befehl, den Sie ausführen möchten, nicht finden kann. Wenn der Befehl erfolgreich ausgeführt wird, werden alle Daten, die er in den Standardausgabestream schreibt, in stdout erfasst, sowie alle Daten, die er an den Standardfehlerstream schreibt, in stderr erfasst.

      Anmerkung: Es ist wichtig, den Unterschied zwischen error und stderr im Auge zu behalten. Wenn die Ausführung des Befehls selbst fehlschlägt, erfasst error den Fehler. Wenn der Befehl ausgeführt wird, aber eine Ausgabe in den Fehlerstream zurückgibt, wird dies von stderr erfasst. Die stabilsten Node.js-Programme verarbeiten alle möglichen Ausgaben für einen untergeordneten Prozess.

      In unserer Callback-Funktion überprüfen wir zunächst, ob wir einen Fehler erhalten haben. Falls dem so ist, stellen wir die message des Fehlers (eine Eigenschaft des Error-Objekts) mit console.error() dar und beenden die Funktion mit return. Wir überprüfen dann, ob der Befehl eine Fehlermeldung und in dem Fall return ausgegeben hat. Wenn der Befehl erfolgreich ausgeführt wird, protokollieren wir seine Ausgabe in der Konsole mit console.log().

      Führen wir diese Datei aus, um sie in Aktion zu sehen. Speichern und schließen Sie nano, indem Sie STRG+X drücken.

      Zurück in Ihrem Terminal führen Sie nun Ihre Anwendung mit dem node-Befehl aus:

      In Ihrem Terminal wird die folgende Ausgabe angezeigt:

      Output

      stdout: total 4.0K -rw-rw-r-- 1 sammy sammy 280 Jul 27 16:35 listFiles.js

      In dieser wird der Inhalt des child-processes-Verzeichnisses in langer Form aufgelistet, zusammen mit der Größe des Inhalts am Anfang. Ihre Ergebnisse haben anstelle von sammy Ihren eigenen Benutzer und Ihre Gruppe. Das zeigt, dass das listFiles.js-Programm den Shell-Befehl ls -lh erfolgreich ausgeführt hat.

      Schauen wir uns nun einen anderen Weg zur Ausführung gleichzeitiger Prozesse an. Das child_process-Modul von Node.js kann auch ausführbare Dateien mit der execFile()-Funktion ausführen. Der Hauptunterschied zwischen den Funktionen execFile() und exec() besteht darin, dass das erste Argument von execFile() nun ein Pfad zu einer ausführbaren Datei anstelle eines Befehls ist. Die Ausgabe der ausführbaren Datei wird in einem Puffer wie exec() gespeichert, auf den wir über eine Callback-Funktion mit error-, stdout– und stderr-Parametern zugreifen.

      Anmerkung: Skripte in Windows wie .bat– und .cmd-Dateien können nicht mit execFile() ausgeführt werden, da die Funktion beim Ausführen der Datei keine Shell erstellt. Unter Unix, Linux und MacOS benötigen ausführbare Skripte nicht immer eine Shell, um ausgeführt zu werden. Windows-Rechner benötigen jedoch eine Shell, um Skripte auszuführen. Um Skriptdateien unter Windows auszuführen, verwenden Sie exec(), da es eine neue Shell erstellt. Alternativ können Sie spawn() verwenden. Sie verwenden es später in diesem Schritt.

      Sie können jedoch .exe-Dateien in Windows erfolgreich mit execFile() ausführen. Die Beschränkung gilt nur für Skriptdateien, die eine Shell zur Ausführung benötigen.

      Beginnen wir mit dem Hinzufügen eines ausführbaren Skripts für execFile(). Wir schreiben ein Bash-Skript, das das Node.js-Logo von der Website von Node.js herunterlädt und es mit Base64 kodiert, um seine Daten in eine Zeichenfolge von ASCII-Zeichen zu konvertieren.

      Erstellen Sie eine neue Shell-Skriptdatei namens processNodejsImage.sh:

      • nano processNodejsImage.sh

      Schreiben Sie nun ein Skript, um das Bild herunterzuladen und mit base64 zu konvertieren:

      ~/child-processes/processNodejsImage.sh

      #!/bin/bash
      curl -s https://nodejs.org/static/images/logos/nodejs-new-pantone-black.svg > nodejs-logo.svg
      base64 nodejs-logo.svg
      

      Die erste Anweisung ist eine Shebang-Anweisung. Sie wird in Unix, Linux und MacOS verwendet, wenn wir eine Shell zur Ausführung unseres Skripts spezifizieren möchten. Die zweite Anweisung ist ein curl-Befehl. Das cURL utility, dessen Befehl curl ist, ist ein Befehlszeilentool, das Daten zu und von einem Server übertragen kann. Wir verwenden cURL, um das Node.js-Logo von der Website herunterzuladen. Dann verwenden wir Umleitung, um die heruntergeladenen Daten in einer neuen Datei nodejs-logo.svg zu speichern. Die letzte Anweisung verwendet das base64-Dienstprogramm zur Codierung der mit cURL heruntergeladenen Datei nodejs-logo.svg. Das Skript gibt dann die codierte Zeichenfolge an die Konsole aus.

      Speichern und schließen Sie, bevor Sie fortfahren.

      Damit unser Node-Programm das bash-Skript ausführen kann, müssen wir es ausführbar machen. Führen Sie dazu Folgendes aus:

      • chmod u+x processNodejsImage.sh

      Dadurch erhält Ihr aktueller Benutzer die Berechtigung, die Datei auszuführen.

      Mit unserem vorhandenen Skript können wir ein neues Node.js-Modul schreiben, um es auszuführen. Dieses Skript verwendet execFile(), um das Skript in einem untergeordneten Prozess auszuführen, wobei etwaige Fehler abgefangen werden und jede Ausgabe in der Konsole angezeigt wird.

      Erstellen Sie in Ihrem Terminal eine neue JavaScript-Datei namens getNodejsImage.js:

      Geben Sie den folgenden Code im Texteditor ein:

      ~/child-processes/getNodejsImage.js

      const { execFile } = require('child_process');
      
      execFile(__dirname + '/processNodejsImage.sh', (error, stdout, stderr) => {
        if (error) {
          console.error(`error: ${error.message}`);
          return;
        }
      
        if (stderr) {
          console.error(`stderr: ${stderr}`);
          return;
        }
      
        console.log(`stdout:n${stdout}`);
      });
      

      Wir verwenden JavaScript-Destrukturierung zum Importieren der execFile()-Funktion aus dem child_process-Modul. Dann verwenden wir diese Funktion, indem wir den Dateipfad als Vorname übergeben. __dirname enthält den Verzeichnispfad des Moduls, in dem es geschrieben ist. Node.js stellt die __dirname-Variable für ein Modul bereit, wenn das Modul ausgeführt wird. Durch die Verwendung von __dirname findet unser Skript immer die Datei processNodejsImage.sh unter verschiedenen Betriebssystemen,unabhängig davon, wo wir getNodejsImage.js ausführen. Beachten Sie, dass sich für unsere aktuelle Projekteinrichtung getNodejsImage.js und processNodejsImage.sh im gleichen Ordner befinden müssen.

      Das zweite Argument ist ein Callback mit den Parametern error, stdout und stderr. Wie bei unserem vorherigen Beispiel, in dem exec() verwendet wurde, überprüfen wir jede mögliche Ausgabe der Skriptdatei und protokollieren sie in der Konsole.

      Speichern Sie in Ihrem Texteditor diese Datei und verlassen Sie den Editor.

      Verwenden Sie in Ihrem Terminal node, um das Modul auszuführen:

      Bei Ausführung dieses Skripts wird eine Ausgabe wie diese erstellt:

      Output

      stdout: PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNDQyLjQgMjcwLjkiPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9IjE4MC43IiB5MT0iODAuNyIge ...

      Beachten Sie, dass wir die Ausgabe in diesem Artikel aufgrund ihrer großen Größe verkürzt haben.

      Bevor der base64-Codierung des Bildes lädt processNodejsImage.sh es zunächst herunter. Sie können auch überprüfen, ob Sie das Bild heruntergeladen haben, indem Sie das aktuelle Verzeichnis inspizieren.

      Führen Sie listFiles.js aus, um die aktualisierte Liste von Dateien in unserem Verzeichnis zu finden:

      Das Skript zeigt Inhalte ähnlich wie folgende im Terminal an:

      Output

      stdout: total 20K -rw-rw-r-- 1 sammy sammy 316 Jul 27 17:56 getNodejsImage.js -rw-rw-r-- 1 sammy sammy 280 Jul 27 16:35 listFiles.js -rw-rw-r-- 1 sammy sammy 5.4K Jul 27 18:01 nodejs-logo.svg -rwxrw-r-- 1 sammy sammy 129 Jul 27 17:56 processNodejsImage.sh

      Wir haben nun processNodejsImage.sh erfolgreich als Kindprozess in Node.js mit der execFile()-Funktion ausgeführt.

      Die Funktionen exec() und execFile() können Befehle auf der Shell des Betriebssystems in einem Node.js-Kindprozess ausführen. Node.js bietet auch eine andere Methode mit ähnlicher Funktionalität, spawn(). Der Unterschied besteht darin, dass wir die Ausgabe der Shell-Befehle nicht auf einmal erhalten, sondern in Stücken über einen Stream. Im nächsten Abschnitt verwenden wir den spawn()-Befehl zur Erstellung eines untergeordneten Prozesses.

      Schritt 2 — Erstellen eines Kindprozesses mit spawn()

      Die spawn()-Funktion führt einen Befehl in einem Prozess aus. Diese Funktion gibt Daten über die Stream-API zurück. Um die Ausgabe des Kindprozesses zu erhalten, müssen wir daher auf Stream-Ereignisse lauschen.

      Streams in Node.js sind Instanzen von Ereignis-Emittern. Wenn Sie mehr über das Lauschen auf Ereignisse und die Grundlagen der Interaktion mit Streams erfahren möchten, können Sie unseren Leitfaden zur Verwendung von Ereigniss-Emittern in Node.js lesen.

      Es ist oft eine gute Idee, spawn() anstatt exec() oder execFile() zu wählen, wenn der Befehl, den Sie ausführen möchten, eine große Menge an Daten ausgeben kann. Bei einem Puffer, wie er von exec() und execFile() verwendet wird, werden alle verarbeiteten Daten im Arbeitsspeicher des Computers gespeichert. Bei großen Datenmengen kann hierbei die Systemleistung sinken. Bei einem Stream werden die Daten in kleinen Stücken verarbeitet und übertragen. Daher können Sie eine große Menge an Daten verarbeiten, ohne zu viel Arbeitsspeicher im selben Moment zu verwenden.

      Sehen wir uns an, wie wir spawn() zur Erstellung eines Kindprozesses verwenden können. Wir schreiben ein neues Node.js-Modul, das einen Kindprozess erstellt, um den Befehl find auszuführen. Wir verwenden den Befehl find , um alle Dateien im aktuellen Verzeichnis aufzulisten.

      Erstellen Sie eine neue Datei namens findFiles.js:

      Beginnen Sie in Ihrem Texteditor mit dem Aufruf des spawn()-Befehls:

      ~/child-processes/findFiles.js

      const { spawn } = require('child_process');
      
      const child = spawn('find', ['.']);
      

      Wir haben zunächst die spawn()-Funktion aus dem child_process-Modul importiert. Dann haben wir die spawn()-Funktion aufgerufen, um einen Kindprozess zu erstellen, der den Befehl find ausführt. Wir halten den Verweis auf den Prozess in der child-Variable, die wir zum Lauschen seiner gestreamten Ereignisse verwenden.

      Das erste Argument in spawn() ist der auszuführende Befehl, in diesem Fall find. Das zweite Argument ist ein Array, das die Argumente für den ausgeführten Befehl enthält. In diesem Fall weisen wir Node.js an, den Befehl find mit dem Argument ., auszuführen. Dadurch wird der Befehl veranlasst, alle Dateien im aktuellen Verzeichnis zu finden. Der äquivalente Befehl im Terminal ist find ..

      Mit den Funktionen exec() und execFile() haben wir die Argumente zusammen mit dem Befehl in einer Zeichenfolge geschrieben. Bei spawn() müssen jedoch alle Argumente für Befehle in das Array eingegeben werden. Das liegt daran, dass spawn(), im Gegensatz zu exec() und execFile(), keine neue Shell erstellt, bevor ein Prozess ausgeführt wird. Um Befehle mit ihren Argumenten in einer einzelnen Zeichenfolge zu haben, ist es auch erforderlich, das Node.js eine neue Shell erstellt.

      Wir fahren mit unserem Modul fort, indem wir Listener für die Ausgabe des Befehls hinzufügen. Fügen Sie die folgenden hervorgehobenen Zeilen hinzu:

      ~/child-processes/findFiles.js

      const { spawn } = require('child_process');
      
      const child = spawn('find', ['.']);
      
      child.stdout.on('data', data => {
        console.log(`stdout:n${data}`);
      });
      
      child.stderr.on('data', data => {
        console.error(`stderr: ${data}`);
      });
      

      Befehle können Daten entweder im stdout-Stream oder im stderr-Stream zurückgeben. Daher fügen Sie Listener für beide hinzu. Sie können Listener hinzufügen, indem Sie die on()-Methode der Objekte jedes Streams aufrufen. Das data-Ereignis aus den Streams gibt uns die Ausgabe des Befehls an diesen Stream. Wann immer wir Daten über einen Stream erhalten, protokollieren wir diese in der Konsole.

      Dann lauschen wird auf zwei andere Ereignisse: das error-Ereignis, wenn der Befehl nicht ausgeführt oder unterbrochen wird, und das close-Ereignis, wenn der Befehl die Ausführung beendet hat und damit den Stream schließt.

      Schließen Sie im Texteditor das Node.js-Modul ab, indem Sie die folgenden hervorgehobenen Zeilen schreiben:

      ~/child-processes/findFiles.js

      const { spawn } = require('child_process');
      
      const child = spawn('find', ['.']);
      
      child.stdout.on('data', (data) => {
        console.log(`stdout:n${data}`);
      });
      
      child.stderr.on('data', (data) => {
        console.error(`stderr: ${data}`);
      });
      
      child.on('error', (error) => {
        console.error(`error: ${error.message}`);
      });
      
      child.on('close', (code) => {
        console.log(`child process exited with code ${code}`);
      });
      

      Für die error– und close-Ereignisse haben Sie einen Listener direkt in der child-Variable eingerichtet. Wenn beim Lauschen auf error-Ereignisse ein Fehler auftritt, stellt Node.js ein Error-Objekt bereit. In diesem Fall protokollieren Sie die message-Eigenschaft des Fehlers.

      Beim Lauschen auf das close-Ereignis stellt Node.js den Exit-Code des Befehls bereit. Ein Exit-Code gibt an, ob der Befehl erfolgreich ausgeführt wurde oder nicht. Wenn ein Befehl ohne Fehler ausgeführt wird, gibt er den geringmöglichsten Wert für einen Exit-Code zurück: 0. Wenn er mit einem Fehler ausgeführt wird, wird ein Code ungleich Null zurückgegeben.

      Das Modul ist komplett. Speichern und schließen Sie nano mit STRG+X.

      Führen Sie nun den Code mit dem node-Befehl aus:

      Nach der Ausführung finden Sie die folgende Ausgabe:

      Output

      stdout: . ./findFiles.js ./listFiles.js ./nodejs-logo.svg ./processNodejsImage.sh ./getNodejsImage.js child process exited with code 0

      Wir finden eine Liste aller Dateien in unserem aktuellen Verzeichnis und den Exit-Code des Befehls, der 0 ist, da die Ausführung erfolgreich war. Unser aktuelles Verzeichnis hat nur eine kleine Anzahl von Dateien. Würden wir diesen Code in unserem Stammverzeichnis ausführen, würde unser Programm jede einzelne Datei in jedem zugänglichen Ordner für unseren Benutzer auflisten. Die Verwendung der spawn()-Funktion ist ideal, da sie eine potenziell so große Ausgabe hat, und weil ihre Streams nicht so viel Arbeitsspeicher benötigen wie ein großer Puffer.

      Bisher haben wir Funktionen zur Erstellung von Kindprozessen verwendet, um externe Befehle in unserem Betriebssystem auszuführen. Node.js bietet auch die Möglichkeit, einen Kindprozess zu erstellen, der andere Node.js-Programme ausführt. Im nächsten Abschnitt verwenden wir die fork()-Funktion zum Erstellen eines Kindprozesses für ein Node.js-Modul.

      Schritt 3 — Erstellen eines Kindprozesses mit fork()

      Node.js bietet die fork()-Funktion, eine Variante von spawn(), um einen Kindprozess zu erstellen, der gleichzeitig ein Node.js-Prozess ist. Der Hauptvorteil der Verwendung von fork() zur Erstellung eines Node.js-Prozesses anstelle von spawn() oder exec() besteht darin, dass fork() die Kommunikation zwischen dem Eltern- und dem Kindprozess ermöglicht.

      Mit fork() kann ein Elternprozess nicht nur Daten aus dem Kindprozess abrufen, sondern auch Nachrichten an den laufenden Kindprozess senden. Ebenso kann der Kindprozess Nachrichten an den Elternprozess senden.

      Sehen wir uns ein Beispiel an, bei dem die Verwendung von fork() zur Erstellung eines neuen Node.js-Kindprozesses die Leistung unserer Anwendung verbessern kann. Node.js-Programme werden in einem einzelnen Prozess ausgeführt. Daher stoppen CPU-intensive Aufgaben wie das Iterieren über große Schleifen oder das Parsing großer JSON-Dateien die Ausführung von anderem JavaScript-Code. Für bestimmte Anwendungen ist dies keine tragfähige Option. Wenn ein Webserver blockiert ist, kann er keine neuen eingehenden Anfragen verarbeiten, bis der blockierende Code seine Ausführung abgeschlossen hat.

      Wir sehen uns das in der Praxis an, indem wir einen Webserver mit zwei Endpunkten erstellen. Ein Endpunkt nimmt eine langsame Berechnung vor, die den Node.js-Prozess blockiert. Der andere Endpunkt gibt ein JSON-Objekt zurück, das hello sagt.

      Erstellen Sie zunächst eine neue Datei namens httpServer.js, die den Code für unseren HTTP-Server haben wird:

      Wir beginnen mit der Einrichtung des HTTP-Servers. Dazu gehört das Importieren des http-Moduls, die Erstellung einer Request Listener-Funktion, die Erstellung eines Server-Objekts und das Lauschen auf Anfragen an das Server-Objekt. Wenn Sie mehr über die Erstellung von HTTP-Servern in Node.js erfahren möchten oder eine Auffrischung zum Thema wünschen, können Sie unseren Leitfaden zum Erstellen eines Web-Servers in Node.js mit dem HTTP-Modul lesen.

      Geben Sie den folgenden Code in Ihren Texteditor ein, um einen HTTP-Server einzurichten:

      ~/child-processes/httpServer.js

      const http = require('http');
      
      const host="localhost";
      const port = 8000;
      
      const requestListener = function (req, res) {};
      
      const server = http.createServer(requestListener);
      server.listen(port, host, () => {
        console.log(`Server is running on http://${host}:${port}`);
      });
      

      Dieser Code erstellt einen HTTP-Server, der unter http://localhost:8000 ausgeführt wird. Er verwendet Template-Literale, um diese URL dynamisch zu generieren.

      Als Nächstes schreiben wir eine absichtlich langsame Funktion, die in einer Schleife 5 Milliarden Mal zählt. Fügen Sie vor der Funktion requestListener() den folgenden Code hinzu:

      ~/child-processes/httpServer.js

      ...
      const port = 8000;
      
      const slowFunction = () => {
        let counter = 0;
        while (counter < 5000000000) {
          counter++;
        }
      
        return counter;
      }
      
      const requestListener = function (req, res) {};
      ...
      

      Dieser verwendet die Syntax der Pfeilfunktion, um eine while-Schleife zu erstellen, die bis 5000000000 zählt.

      Um dieses Modul abzuschließen, müssen wir der requestListener()-Funktion Code hinzufügen. Unsere Funktion ruft die slowFunction() auf dem Unterpfad auf und gibt eine kleine JSON-Nachricht für die andere zurück. Fügen Sie dem Modul folgenden Code hinzu:

      ~/child-processes/httpServer.js

      ...
      const requestListener = function (req, res) {
        if (req.url === '/total') {
          let slowResult = slowFunction();
          let message = `{"totalCount":${slowResult}}`;
      
          console.log('Returning /total results');
          res.setHeader('Content-Type', 'application/json');
          res.writeHead(200);
          res.end(message);
        } else if (req.url === '/hello') {
          console.log('Returning /hello results');
          res.setHeader('Content-Type', 'application/json');
          res.writeHead(200);
          res.end(`{"message":"hello"}`);
        }
      };
      ...
      

      Wenn der Benutzer den Server am Unterpfad /total erreicht, führen wir slowFunction() aus. Wenn wir auf den Unterpfad /hello treffen, geben wir diese JSON-Nachricht zurück: {"message":"hello"}.

      Speichern und schließen Sie die Datei, indem Sie STRG+X drücken.

      Zum Testen führen Sie dieses Server-Modul mit node aus:

      Wenn unser Server startet, zeigt die Konsole Folgendes an:

      Output

      Server is running on http://localhost:8000

      Um die Leistung unseres Moduls zu testen, öffnen Sie nun zwei zusätzliche Terminals. Verwenden Sie im ersten Terminal den curl-Befehl, um eine Anfrage an den /total-Endpunkt zu stellen, von dem wir erwarten, dass er langsam ist:

      • curl http://localhost:8000/total

      Verwenden Sie im anderen Terminal curl, um eine Anfrage an den /hello-Endpunkt wie folgt zu stellen:

      • curl http://localhost:8000/hello

      Die erste Anfrage gibt folgende JSON zurück:

      Output

      {"totalCount":5000000000}

      Die zweite Anfrage gibt diese JSON zurück:

      Output

      {"message":"hello"}

      Die Anfrage an /hello wurde erst nach der Anfrage an /total abgeschlossen. Die slowFunction() hat die Ausführung allen anderen Codes blockiert, während sie noch in ihrer Schleife war. Sie können dies überprüfen, indem Sie die Ausgabe des Node.js-Servers anschauen, die in Ihrem ursprünglichen Terminal protokolliert worden ist:

      Output

      Returning /total results Returning /hello results

      Um den blockierenden Code zu verarbeiten und gleichzeitig eingehende Anfragen zu akzeptieren, können wir den blockierenden Code mit fork() in einen Kindprozess verschieben. Wir verschieben den blockierenden Code in sein eigenes Modul. Der Node.js-Server erstellt dann einen Kindprozess, wenn jemand auf den /total-Endpunkt zugreift und lauscht auf Ergebnisse aus diesem Kindprozess.

      Refaktorieren Sie den Server, indem Sie zunächst ein neues Modul namens getCount.js erstellen, das slowFunction(): enthält:

      Geben Sie nun den Code für slowFunction() erneut ein:

      ~/child-processes/getCount.js

      const slowFunction = () => {
        let counter = 0;
        while (counter < 5000000000) {
          counter++;
        }
      
        return counter;
      }
      

      Da dieses Modul ein mit fork() erstellter untergeordneter Prozess ist, können wir auch Code hinzufügen, um mit dem übergeordneten Prozess zu kommunizieren, wenn slowFunction() die Verarbeitung abgeschlossen hat. Fügen Sie den folgenden Code-Block hinzu, der eine Nachricht an den Elternprozess mit der JSON zur Rückgabe an den Benutzer sendet:

      ~/child-processes/getCount.js

      const slowFunction = () => {
        let counter = 0;
        while (counter < 5000000000) {
          counter++;
        }
      
        return counter;
      }
      
      process.on('message', (message) => {
        if (message == 'START') {
          console.log('Child process received START message');
          let slowResult = slowFunction();
          let message = `{"totalCount":${slowResult}}`;
          process.send(message);
        }
      });
      

      Gehen wird diesen Code-Block durch. Die von fork() erstellten Nachrichten zwischen einem Eltern- und Kindprozess sind über das globale process-Objekt von Node.js zugänglich. Wir fügen der process-Variable einen Listener hinzu, um nach message-Ereignissen zu suchen. Sobald wir ein message-Ereignis erhalten, überprüfen wir, ob es das START-Ereignis ist. Unser Servercode sendet das START-Ereignis, wenn jemand auf den /total-Endpunkt zugreift. Nach dem Erhalt dieses Ereignisses führen wir slowFunction() aus und erstellen mit dem Ergebnis der Funktion eine JSON-Zeichenfolge. Wir verwenden process.send(), um eine Nachricht an den übergeordneten Prozess zu senden.

      Speichern und schließen Sie getCount.js, indem Sie STRG+X in nano eingeben.

      Wir ändern nun die Datei httpServer.js so, dass sie anstatt slowFunction() aufzurufen, einen Kindprozess erstellt, der getCount.js ausführt.

      Öffnen Sie httpServer.js erneut mit nano:

      Importieren Sie zunächst die fork()-Funktion aus dem child_process-Modul:

      ~/child-processes/httpServer.js

      const http = require('http');
      const { fork } = require('child_process');
      ...
      

      Als Nächstes entfernen wir die slowFunction() aus diesem Modul und ändern die requestListener()-Funktion, um einen Kindprozess zu erstellen. Ändern Sie den Code in Ihrer Datei, damit er so aussieht:

      ~/child-processes/httpServer.js

      ...
      const port = 8000;
      
      const requestListener = function (req, res) {
        if (req.url === '/total') {
          const child = fork(__dirname + '/getCount');
      
          child.on('message', (message) => {
            console.log('Returning /total results');
            res.setHeader('Content-Type', 'application/json');
            res.writeHead(200);
            res.end(message);
          });
      
          child.send('START');
        } else if (req.url === '/hello') {
          console.log('Returning /hello results');
          res.setHeader('Content-Type', 'application/json');
          res.writeHead(200);
          res.end(`{"message":"hello"}`);
        }
      };
      ...
      

      Wenn jemand zum Endpunkt /total geht, erstellen wir nun einen neuen Kindprozess mit fork(). Das Argument von fork() ist der Pfad zum Node.js-Modul. In diesem Fall ist es die getCount.js-Detei in unserem aktuellen Verzeichnis, die wir von __dirname erhalten. Der Verweis auf diesen Kindprozess wird in einer child-Variablen gespeichert.

      Dann fügen wir dem child-Objekt einen Listener hinzu. Dieser Listener erfasst alle Nachrichten, die der Kindprozess uns gibt. In diesem Fall gibt getCount.js eine JSON-Zeichenfolge mit der Gesamtzahl zurück, die von der while-Schleife gezählt wurde. Wenn wir diese Nachricht erhalten, senden wir die JSON an den Benutzer.

      Wir verwenden die send()-Funktion der child-Variablen, um die Nachricht zu übergeben. Dieses Programm sendet die Message START, mit der die Ausführung von slowFunction() im untergeordneten Prozess beginnt.

      Speichern und schließen Sie nano, indem Sie STRG+X drücken.

      Um die Verbesserung mit fork() auf HTTP-Server zu testen, beginnen Sie mit der Ausführung der httpServer.js-Datei mit node:

      Wie zuvor gibt sie beim Starten die folgende Nachricht aus:

      Output

      Server is running on http://localhost:8000

      Um den Server zu testen, benötigen wir so wie beim ersten Mal zwei weitere Terminals. Sie können diese erneut verwenden, wenn sie noch offen sind.

      Verwenden Sie im ersten Terminal den curl-Befehl, um eine Anfrage an den /total-Endpunkt zu stellen, deren Berechnung eine Weile dauert:

      • curl http://localhost:8000/total

      Verwenden Sie im anderen Terminal curl, um eine Anfrage an den /hello-Endpunkt zu stellen, der in kurzer Zeit reagiert:

      • curl http://localhost:8000/hello

      Die erste Anfrage gibt folgende JSON zurück:

      Output

      {"totalCount":5000000000}

      Die zweite Anfrage gibt diese JSON zurück:

      Output

      {"message":"hello"}

      Anders als beim ersten Versuch wird die zweite Anfrage an /hello sofort ausgeführt. Sie können dies bestätigen, indem Sie die Protokolle überprüfen, die folgendermaßen aussehen:

      Output

      Child process received START message Returning /hello results Returning /total results

      Diese Protokolle zeigen, dass die Anfrage für den /hello-Endpunkt nach Erstellung des untergeordneten Prozesses, aber vor Beendigung des untergeordneten Prozesses ausgeführt wurde.

      Da wir den blockierenden Code in einem Kindprozess mit fork() verschoben haben, konnte der Server nach wie vor auf andere Anfragen reagieren und anderen JavaScript-Code ausführen. Aufgrund der Fähigkeit der fork()-Funktion, Nachrichten zu übergeben, können wir kontrollieren, wann ein Kindprozess eine Aktivität beginnt, und wir können Daten von einem Kindprozess an einen Elternprozess zurückgeben.

      Zusammenfassung

      In diesem Artikel haben Sie verschiedene Funktionen zur Erstellung eines Kindprozesses in Node.js verwendet. Sie haben zunächst Kindprozesse mit exec() erstellt, um Shell-Befehle aus Node.js-Code auszuführen. Sie haben dann eine ausführbare Datei mit der execFile()-Funktion ausgeführt. Sie haben sich die Funktion spawn() angeschaut, die auch Befehle ausführen kann, Daten jedoch über einen Stream zurückgibt und anders als exec() und execFile() keine Shell startet. Abschließend haben Sie die Funktion fork() verwendet, um eine zweigleisige Kommunikation zwischen dem Eltern- und Kindprozess zu ermöglichen.

      Um mehr über das child_process-Modul zu erfahren, können Sie die Node.js-Dokumentation lesen. Wenn Sie Node.js weiter lernen möchten, können Sie zur Codieren in Node-Reihe zurückkehren oder Programmierprojekte und -einstellungen auf unserer Node-Themenseite durchsuchen.



      Source link