Apa arti sebenarnya dari middleware dan app.use di Expressjs?


228

Hampir setiap aplikasi Express yang saya lihat memiliki app.usepernyataan untuk middleware tetapi saya belum menemukan penjelasan yang jelas dan ringkas tentang apa sebenarnya middleware dan apa yang dilakukan app.usepernyataan itu. Bahkan dokumen ekspres sendiri agak kabur dalam hal ini. Bisakah Anda menjelaskan konsep-konsep ini untuk saya?


3
pertanyaan serupa untuk referensi (yang ini dibuat sebelumnya): stackoverflow.com/questions/11321635/…
ericsoco

43
^ Ha! Dua pertanyaan ini saling referensi dalam komentar.
Julian H. Lam

17
Jadi ini adalah Referensi Cirular.
Steve K

6
Express.js Middleware Demystified Sebuah posting blog yang bagus tentang topik ini. Ini sudah disalin di sini sebelumnya, yang tentu saja plagiarisme, tetapi posting asli masih sangat membantu jadi saya meninggalkan tautan di sini.
totymedli

1
Saya menulis artikel di middleware express.js. Inilah tautannya: nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe

Jawaban:


111

middleware

Saya setengah jalan memisahkan konsep middleware dalam proyek baru.

Middleware memungkinkan Anda untuk menentukan setumpuk tindakan yang harus Anda lalui. Express server sendiri adalah setumpuk middlewares.

// express
var app = express();
// middleware
var stack = middleware();

Kemudian Anda bisa menambahkan lapisan ke tumpukan middleware dengan memanggil .use

// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
  next();
});

Lapisan dalam tumpukan middleware adalah fungsi, yang mengambil n parameter (2 untuk express, req& res) dan sebuah nextfungsi.

Middleware mengharapkan layer untuk melakukan beberapa perhitungan, menambah parameter dan kemudian memanggil next.

Tumpukan tidak melakukan apa pun kecuali Anda menanganinya. Express akan menangani tumpukan setiap kali permintaan HTTP masuk ditangkap di server. Dengan middleware Anda menangani tumpukan secara manual.

// express, you need to do nothing
// middleware
stack.handle(someData);

Contoh yang lebih lengkap:

var middleware = require("../src/middleware.js");

var stack = middleware(function(data, next) {
    data.foo = data.data*2;
    next();
}, function(data, next) {
    setTimeout(function() {
        data.async = true;
        next();
    }, 100)
}, function(data) {
    console.log(data);
});

stack.handle({
    "data": 42
})

Dalam istilah ekspres, Anda cukup menentukan setumpuk operasi yang ingin Anda ekspresikan untuk setiap permintaan HTTP yang masuk.

Dalam hal mengekspresikan (daripada menghubungkan), Anda memiliki middleware global dan rute middleware khusus. Ini berarti Anda dapat melampirkan tumpukan middleware ke setiap permintaan HTTP yang masuk atau hanya melampirkannya ke permintaan HTTP yang berinteraksi dengan rute tertentu.

Contoh lanjutan dari ekspres & middleware:

// middleware 

var stack = middleware(function(req, res, next) {
    users.getAll(function(err, users) {
        if (err) next(err);
        req.users = users;
        next();  
    });
}, function(req, res, next) {
    posts.getAll(function(err, posts) {
        if (err) next(err);
        req.posts = posts;
        next();
    })
}, function(req, res, next) {
    req.posts.forEach(function(post) {
        post.user = req.users[post.userId];
    });

    res.render("blog/posts", {
        "posts": req.posts
    });
});

var app = express.createServer();

app.get("/posts", function(req, res) {
   stack.handle(req, res); 
});

// express

var app = express.createServer();

app.get("/posts", [
    function(req, res, next) {
        users.getAll(function(err, users) {
            if (err) next(err);
            req.users = users;
            next();  
        });
    }, function(req, res, next) {
        posts.getAll(function(err, posts) {
            if (err) next(err);
            req.posts = posts;
            next();
        })
    }, function(req, res, next) {
        req.posts.forEach(function(post) {
            post.user = req.users[post.userId];
        });

        res.render("blog/posts", {
            "posts": req.posts
        });
    }
], function(req, res) {
   stack.handle(req, res); 
});

4
Hmm ... apakah middleware dalam hal ini perpustakaan Anda sendiri atau bagian dari ekspres?
iZ.

5
Keren. Saya masih sedikit bingung dengan app.use()sintaksisnya. Apa nilai pengembalian sebenarnya dari middleware dan apa usehubungannya dengan itu?
iZ.

9
@ iZ use menambahkannya ke stack. Lalu setiap permintaan melewati stack.
Raynos

7
@Raynos, tautan ke proyek Anda, "middleware", rusak.
Lee

1
@ Raynos tapi saya melihat middleware masih digunakan di Express? apa maksudmu itu nuked?
Timo Huovinen

60

Setelah menyederhanakan berbagai hal, server web dapat dilihat sebagai fungsi yang menerima permintaan dan menampilkan respons. Jadi jika Anda melihat server web sebagai suatu fungsi, Anda dapat mengaturnya menjadi beberapa bagian dan memisahkannya menjadi fungsi-fungsi yang lebih kecil sehingga komposisi mereka menjadi fungsi asli.

Middlewares adalah fungsi yang lebih kecil yang dapat Anda buat dengan orang lain dan manfaat yang jelas adalah bahwa Anda dapat menggunakannya kembali.


33

Saya menambahkan jawaban terlambat untuk menambahkan sesuatu yang tidak disebutkan dalam jawaban sebelumnya.

Sekarang sudah jelas bahwa middleware berfungsi antara permintaan klien dan jawaban server . Fungsionalitas middleware paling umum yang diperlukan adalah mengelola kesalahan, interaksi basis data, mendapatkan info dari file statis atau sumber daya lainnya. Untuk pindah ke tumpukan middleware panggilan balik berikutnya harus dipanggil, Anda bisa melihatnya di akhir fungsi middleware untuk pindah ke langkah berikutnya dalam aliran.

Anda dapat menggunakan app.usependekatan dan memiliki alur seperti ini :

var express = require('express'),
    app = express.createServer(),                                                                                                                                                 
    port = 1337;

function middleHandler(req, res, next) {
    console.log("execute middle ware");
    next();
}

app.use(function (req, res, next) {
    console.log("first middle ware");                                                                                                             
    next();
});

app.use(function (req, res, next) {
    console.log("second middle ware");                                                                                                             
    next();
});

app.get('/', middleHandler, function (req, res) {
    console.log("end middleware function");
    res.send("page render finished");
});

app.listen(port);
console.log('start server');

tetapi Anda juga dapat menggunakan pendekatan lain dan meneruskan setiap middleware sebagai argumen fungsi. Berikut adalah contoh dari situs web MooTools Nodejs di mana perangkat makan tengah mendapatkan aliran Twitter, Github, dan Blog sebelum responsedikirim kembali ke klien. Perhatikan bagaimana fungsi dilewatkan sebagai argumen di app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. Menggunakan app.gethanya akan dipanggil untuk permintaan GET, app.useakan dipanggil untuk semua permintaan.

// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
    org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
    blogData.get(function(err, blog) {
        if (err) next(err);
        res.locals.lastBlogPost = blog.posts[0];
        next();
    });
}

// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
    res.render('index', {
        title: 'MooTools',
        site: 'mootools',
        lastBlogPost: res.locals.lastBlogPost,
        tweetFeed: res.locals.twitter
    });
});

2
Saya mencari jawaban apakah Express.js mendukung pemasangan middleware berbasis rute (BUKAN Router)? Tampaknya Anda telah menunjukkannya dalam jawaban Anda.
Selçuk

Bisakah Anda menjelaskan contoh di atas ?, bagaimana Anda bisa memasukkan begitu banyak fungsi ke app.get (...) dan urutan apa namanya?
Tanner Summers

2
Hai @TannerSummers, .get()metode ini mengambil 3 jenis argumen: yang pertama, yang terakhir dan yang di tengah. Secara internal mendeteksi jika ada lebih banyak argumen dari 2 dan menggunakan mereka (yang tengah) sebagai fungsi middleware, memanggil mereka dari kiri ke kanan.
Sergio

22

panduan expressjs memiliki jawaban yang cukup rapi untuk pertanyaan Anda, saya sangat menyarankan Anda untuk membacanya, saya memposting potongan pendek panduan ini, panduan ini cukup baik.

Menulis middleware untuk digunakan dalam aplikasi Express

Gambaran

Fungsi Middleware adalah fungsi yang memiliki akses ke objek permintaan ( req ), objek respons ( res ), dan fungsi berikutnya dalam siklus permintaan-respons aplikasi. Fungsi selanjutnya adalah fungsi di router Express yang, ketika dipanggil, mengeksekusi middleware menggantikan middleware saat ini.

Fungsi Middleware dapat melakukan tugas-tugas berikut:

  • Jalankan kode apa pun.
  • Buat perubahan pada permintaan dan objek respons.
  • Akhiri siklus permintaan-respons.
  • Panggil middleware berikutnya di tumpukan.

Jika fungsi middleware saat ini tidak mengakhiri siklus permintaan-respons, ia harus memanggil next () untuk memberikan kontrol ke fungsi middleware berikutnya. Jika tidak, permintaan akan dibiarkan menggantung.

masukkan deskripsi gambar di sini

Contoh

Berikut adalah contoh aplikasi Express "Hello World" sederhana. Sisa dari artikel ini akan mendefinisikan dan menambahkan dua fungsi middleware ke aplikasi: satu disebut myLogger yang mencetak pesan log sederhana dan satu lagi yang disebut requestTime 1 yang menampilkan timestamp dari permintaan HTTP.

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)   

Fungsi Middleware myLogger

Berikut adalah contoh sederhana dari fungsi middleware yang disebut "myLogger". Fungsi ini hanya mencetak "LOGGED" ketika permintaan ke aplikasi melewatinya. Fungsi middleware ditugaskan ke variabel bernama myLogger.

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

Perhatikan panggilan di atas ke berikutnya () . Memanggil fungsi ini memanggil fungsi middleware berikutnya dalam aplikasi. Fungsi () berikutnya bukan bagian dari Node.js atau Express API, tetapi argumen ketiga yang diteruskan ke fungsi middleware. Fungsi next () bisa dinamai apa saja, tetapi dengan konvensi itu selalu dinamai “next”. Untuk menghindari kebingungan, selalu gunakan konvensi ini.

Untuk memuat fungsi middleware, panggil app.use () , tentukan fungsi middleware. Sebagai contoh, kode berikut memuat fungsi middleware myLogger sebelum rute ke jalur root (/).

var express = require('express')
var app = express()

var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)

Setiap kali aplikasi menerima permintaan, itu mencetak pesan "LOGGED" ke terminal.

Urutan pemuatan middleware penting: fungsi middleware yang dimuat pertama juga dijalankan terlebih dahulu.

Jika myLogger dimuat setelah rute ke jalur root, permintaan tidak pernah mencapainya dan aplikasi tidak mencetak "LOGGED", karena pengendali rute jalur root mengakhiri siklus permintaan-respons.

Fungsi middleware myLogger cukup mencetak pesan, kemudian meneruskan permintaan ke fungsi middleware berikutnya di stack dengan memanggil fungsi next () .


  1. Posting ini hanya akan berisi middleware myLogger, untuk posting selanjutnya Anda bisa pergi ke panduan expressjs asli di sini .


1
Penjelasan yang sangat bagus.
Drumbeg

Ini tersedia di situs ekspres di sini expressjs.com/en/guide/writing-middleware.html , itu sangat bagus. Saya heran mengapa tidak ada yang menyebutkannya sejauh ini.
Suraj Jain

2
Bagus Ini penjelasan paling jelas yang pernah saya lihat di sini dan ya, aneh bahwa tidak ada yang merujuknya!
Drumbeg

1
Dijelaskan dengan baik
Rehan Shikkalgar

Urutan pemuatan middleware penting: fungsi middleware yang dimuat pertama juga dijalankan terlebih dahulu. : Ini adalah catatan penting. Tidak ada jawaban lain yang menyebutkan ini. Untuk pemula yang hanya bekerja pada python, ini sangat penting karena hal-hal ini mungkin belum pernah ditemukan.
Tessaracter

11

===== Penjelasan sangat sangat sederhana =====

Middlewares sering digunakan dalam konteks kerangka Express.js dan merupakan konsep dasar untuk node.js. Singkatnya, pada dasarnya fungsi yang memiliki akses ke objek permintaan dan respons aplikasi Anda. Cara saya ingin memikirkannya, adalah serangkaian 'pemeriksaan / pra-layar' yang diminta melalui permintaan sebelum ditangani oleh aplikasi. Misalnya, Middlewares akan sangat cocok untuk menentukan apakah permintaan tersebut diautentikasi sebelum melanjutkan ke aplikasi dan mengembalikan halaman login jika permintaan tersebut tidak diautentikasi atau untuk mencatat setiap permintaan. Banyak middlewares pihak ketiga yang tersedia yang memungkinkan beragam fungsionalitas.

Contoh Middleware sederhana:

var app = express();
app.use(function(req,res,next)){
    console.log("Request URL - "req.url);
    next();
}

Kode di atas akan dieksekusi untuk setiap permintaan yang masuk dan akan mencatat url permintaan, metode next () pada dasarnya memungkinkan program untuk melanjutkan. Jika fungsi next () tidak dipanggil, program tidak akan melanjutkan lebih jauh dan akan berhenti pada pelaksanaan middleware.

Beberapa Middleware Gotchas:

  1. Urutan middlewares dalam aplikasi Anda penting, karena permintaan akan melewati masing-masing secara berurutan.
  2. Lupa memanggil metode () berikutnya dalam fungsi middleware Anda dapat menghentikan pemrosesan permintaan Anda.
  3. Setiap perubahan objek req dan res dalam fungsi middleware, akan membuat perubahan tersedia untuk bagian lain dari aplikasi yang menggunakan req dan res

1
Terima kasih banyak! ini adalah penjelasan terbaik sejauh ini untuk memahami ini. Sebuah pertanyaan, saya membaca beberapa kode dengan middleware dan tidak memanggil next()tetapi return next(). Apa bedanya?
KansaiRobot

Terima kasih banyak teman untuk kata-kata baik ... kami lakukan next()karena kami ingin middleware berikutnya dipanggil, saya tidak berpikir next()atau return next(), harus membuat perbedaan! Masih tergantung pada apa kodenya ...
Vaibhav Bacchav

7

Middlewares adalah fungsi yang dieksekusi di tengah setelah input / sumber kemudian menghasilkan output yang bisa menjadi output akhir atau dapat digunakan oleh middleware berikutnya sampai siklus selesai.

Ini seperti sebuah produk yang melewati jalur perakitan di mana ia akan dimodifikasi ketika bergerak sepanjang sampai selesai, dievaluasi atau ditolak.

Middleware mengharapkan beberapa nilai untuk bekerja (yaitu nilai parameter) dan berdasarkan beberapa logika middleware akan memanggil atau tidak memanggil middleware berikutnya atau mengirim respons kembali ke klien.

Jika Anda masih tidak dapat memahami konsep middleware, itu dengan cara yang mirip dengan dekorator atau pola rantai komando.


5

Middleware adalah subset dari fungsi berantai yang dipanggil oleh lapisan perutean Express js sebelum penangan yang ditentukan pengguna dipanggil. Fungsi-fungsi Middleware memiliki akses penuh ke objek permintaan dan respons dan dapat memodifikasi salah satunya.

Rantai middleware selalu disebut dalam urutan yang tepat di mana ia telah didefinisikan, sehingga sangat penting bagi Anda untuk mengetahui dengan tepat apa yang dilakukan sepotong middleware tertentu.
Setelah fungsi middleware selesai, ia memanggil fungsi berikutnya dalam rantai dengan memanggil argumen berikutnya sebagai fungsi.
Setelah rantai lengkap dijalankan, penangan permintaan pengguna dipanggil.


1

Buat semuanya tetap sederhana, bung!

Catatan: jawabannya terkait dengan kasus middlware bawaan ExpressJS, namun ada beberapa definisi dan kasus penggunaan middlware.

Dari sudut pandang saya, middleware bertindak sebagai fungsi utilitas atau pembantu tetapi aktivasi dan penggunaannya sepenuhnya opsional dengan menggunakan kode app.use('path', /* define or use builtin middleware */)yang tidak ingin dari kami untuk menulis beberapa kode untuk melakukan tugas yang sangat umum yang diperlukan untuk setiap permintaan HTTP klien kami seperti memproses cookie, token CSRF dan ..., yang sangat umum di sebagian besar aplikasi sehingga middleware dapat membantu kami melakukan semua ini untuk setiap permintaan HTTP klien kami dalam beberapa tumpukan, urutan, atau urutan operasi, kemudian berikan hasil proses sebagai satu unit permintaan klien .

Contoh:

Menerima permintaan klien dan memberikan tanggapan balik kepada mereka sesuai dengan permintaan mereka adalah sifat dari teknologi server web.

Bayangkan jika kita memberikan respons hanya dengan "Halo, dunia!" teks untuk permintaan GET HTTP ke root URI server web kami adalah skenario yang sangat sederhana dan tidak memerlukan yang lain, tetapi sebaliknya jika kami memeriksa pengguna yang saat ini masuk dan kemudian merespons dengan "Halo, Nama Pengguna!" membutuhkan sesuatu yang lebih dari biasanya dalam hal ini kami membutuhkan middleware untuk memproses semua metadata permintaan klien dan memberikan kami informasi identifikasi yang diambil dari permintaan klien kemudian menurut info itu kami dapat secara unik mengidentifikasi pengguna kami saat ini dan dimungkinkan untuk menanggapinya / dia dengan beberapa data terkait.

Semoga bisa membantu seseorang!


-1

Dalam istilah yang sangat mendasar jika saya ingin menjelaskannya seperti ini saya belajar ini dari traversymedia youtube channel express crash course.
ok jadi middle ware adalah fungsi yang dijalankan setelah Anda melakukan panggilan ke rute Anda seperti ini.

var logger = function(req, res, next){
   console.log('logging...');
   next();
}

app.use(logger);

Fungsi logger ini dijalankan setiap kali Anda me-refresh halaman Anda yang berarti Anda dapat menulis apa pun di dalamnya yang harus Anda lakukan setelah halaman Anda diberikan operasi panggilan api apa pun, atur ulang semuanya pada dasarnya apa saja. dan letakkan middleware ini sebelum urutan fungsi rute Anda dari middleware benar-benar penting atau tidak berfungsi

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.