وحدة خفيفة الوزن التي تجلب API Fetch إلى Node.js.

قد تبحث عن مستندات V2
بدلاً من تنفيذ XMLHttpRequest في node.js لتشغيل polyfill الخاصة بالمستعرض ، لماذا لا تنتقل من http الأصلي إلى fetch API مباشرة؟ وبالتالي ، فإن node-fetch ، رمز الحد الأدنى window.fetch .
انظر Jason Miller's Isomorphic-Unfetch أو Leonardo Quixada المتقاطع للاستخدام المتساوي (صادرات node-fetch لصالح الخادم ، whatwg-fetch بالنسبة للعميل).
window.fetch API.res.text() و res.json() ) إلى UTF-8 تلقائيًا.window.fetch . لا تتردد في فتح مشكلة. يتطلب الإصدار المستقر الحالي ( 3.x ) على الأقل node.js 12.20.0.
npm install node-fetch import fetch from 'node-fetch' ; node-fetch من V3 هي وحدة ESM فقط-أنت غير قادر على استيرادها بـ require() .
إذا لم تتمكن من التبديل إلى ESM ، فيرجى استخدام V2 الذي يظل متوافقًا مع CommonJs. ستستمر نشر إصلاحات الأخطاء الحرجة لـ V2.
npm install node-fetch@2 بدلاً من ذلك ، يمكنك استخدام دالة isync import() من commonjs لتحميل node-fetch بشكل غير متزامن:
// mod.cjs
const fetch = ( ... args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ... args ) ) ; لاستخدام fetch() دون استيراده ، يمكنك تصحيح الكائن global في العقدة:
// fetch-polyfill.js
import fetch , {
Blob ,
blobFrom ,
blobFromSync ,
File ,
fileFrom ,
fileFromSync ,
FormData ,
Headers ,
Request ,
Response ,
} from 'node-fetch'
if ( ! globalThis . fetch ) {
globalThis . fetch = fetch
globalThis . Headers = Headers
globalThis . Request = Request
globalThis . Response = Response
}
// index.js
import './fetch-polyfill'
// ... باستخدام إصدار قديم من Node-Betch؟ تحقق من الملفات التالية:
ملاحظة: تم تحديث الوثائق أدناه مع إصدارات 3.x ، إذا كنت تستخدم إصدارًا قديمًا ، فيرجى التحقق من كيفية الترقية.
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://github.com/' ) ;
const body = await response . text ( ) ;
console . log ( body ) ; import fetch from 'node-fetch' ;
const response = await fetch ( 'https://api.github.com/users/github' ) ;
const data = await response . json ( ) ;
console . log ( data ) ; import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/post' , { method : 'POST' , body : 'a=1' } ) ;
const data = await response . json ( ) ;
console . log ( data ) ; import fetch from 'node-fetch' ;
const body = { a : 1 } ;
const response = await fetch ( 'https://httpbin.org/post' , {
method : 'post' ,
body : JSON . stringify ( body ) ,
headers : { 'Content-Type' : 'application/json' }
} ) ;
const data = await response . json ( ) ;
console . log ( data ) ; يتوفر URLSearchParams على الكائن العالمي في node.js اعتبارًا من V10.0.0. انظر الوثائق الرسمية لمزيد من أساليب الاستخدام.
ملاحظة: يتم تعيين رأس Content-Type تلقائيًا فقط على x-www-form-urlencoded عندما يتم إعطاء مثيل من URLSearchParams على هذا النحو:
import fetch from 'node-fetch' ;
const params = new URLSearchParams ( ) ;
params . append ( 'a' , 1 ) ;
const response = await fetch ( 'https://httpbin.org/post' , { method : 'POST' , body : params } ) ;
const data = await response . json ( ) ;
console . log ( data ) ; ملاحظة: استجابات 3xx-5xx ليست استثناءات ، ويجب معالجتها في then() ، راجع القسم التالي.
إن لف وظيفة الجلب في كتلة try/catch سيحصل على جميع الاستثناءات ، مثل الأخطاء التي تنشأ من مكتبات Node Core ، مثل أخطاء الشبكة ، والأخطاء التشغيلية التي هي مثيلات من Fetcherror. راجع وثيقة معالجة الخطأ لمزيد من التفاصيل.
import fetch from 'node-fetch' ;
try {
await fetch ( 'https://domain.invalid/' ) ;
} catch ( error ) {
console . log ( error ) ;
}من الشائع إنشاء دالة مساعد للتحقق من أن الاستجابة لا تحتوي على استجابات خطأ عميل (4xx) أو الخادم (5xx):
import fetch from 'node-fetch' ;
class HTTPResponseError extends Error {
constructor ( response ) {
super ( `HTTP Error Response: ${ response . status } ${ response . statusText } ` ) ;
this . response = response ;
}
}
const checkStatus = response => {
if ( response . ok ) {
// response.status >= 200 && response.status < 300
return response ;
} else {
throw new HTTPResponseError ( response ) ;
}
}
const response = await fetch ( 'https://httpbin.org/status/400' ) ;
try {
checkStatus ( response ) ;
} catch ( error ) {
console . error ( error ) ;
const errorBody = await error . response . text ( ) ;
console . error ( `Error body: ${ errorBody } ` ) ;
}لا يتم تخزين ملفات تعريف الارتباط افتراضيًا. ومع ذلك ، يمكن استخراج ملفات تعريف الارتباط وإقرارها عن طريق التلاعب برؤوس الطلب ورؤوس الاستجابة. انظر استخراج رأس مجموعة cookie للحصول على التفاصيل.
تتمثل "Node.js Way" في استخدام التدفقات عند الإمكان. يمكنك الأنابيب res.body إلى دفق آخر. يستخدم هذا المثال Stream.pipeline لإرفاق معالجات خطأ الدفق وانتظر حتى يكتمل التنزيل.
import { createWriteStream } from 'node:fs' ;
import { pipeline } from 'node:stream' ;
import { promisify } from 'node:util'
import fetch from 'node-fetch' ;
const streamPipeline = promisify ( pipeline ) ;
const response = await fetch ( 'https://github.githubassets.com/images/modules/logos_page/Octocat.png' ) ;
if ( ! response . ok ) throw new Error ( `unexpected response ${ response . statusText } ` ) ;
await streamPipeline ( response . body , createWriteStream ( './octocat.png' ) ) ; في Node.js 14 ، يمكنك أيضًا استخدام متكررات Async لقراءة body ؛ ومع ذلك ، كن حذرًا في التقاط الأخطاء - كلما طالما يتم تشغيل الاستجابة ، زاد احتمال مواجهة خطأ.
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/stream/3' ) ;
try {
for await ( const chunk of response . body ) {
console . dir ( JSON . parse ( chunk . toString ( ) ) ) ;
}
} catch ( err ) {
console . error ( err . stack ) ;
} في Node.js 12 ، يمكنك أيضًا استخدام متكررات Async لقراءة body ؛ ومع ذلك ، لم تنضج تكرارات ASYNC مع تيارات حتى Node.js 14 ، لذلك تحتاج إلى القيام ببعض الأعمال الإضافية للتأكد من أنك تتعامل مع الأخطاء مباشرة من الدفق وانتظر استجابةها لإغلاقها بالكامل.
import fetch from 'node-fetch' ;
const read = async body => {
let error ;
body . on ( 'error' , err => {
error = err ;
} ) ;
for await ( const chunk of body ) {
console . dir ( JSON . parse ( chunk . toString ( ) ) ) ;
}
return new Promise ( ( resolve , reject ) => {
body . on ( 'close' , ( ) => {
error ? reject ( error ) : resolve ( ) ;
} ) ;
} ) ;
} ;
try {
const response = await fetch ( 'https://httpbin.org/stream/3' ) ;
await read ( response . body ) ;
} catch ( err ) {
console . error ( err . stack ) ;
} import fetch from 'node-fetch' ;
const response = await fetch ( 'https://github.com/' ) ;
console . log ( response . ok ) ;
console . log ( response . status ) ;
console . log ( response . statusText ) ;
console . log ( response . headers . raw ( ) ) ;
console . log ( response . headers . get ( 'content-type' ) ) ; على عكس المتصفحات ، يمكنك الوصول إلى رؤوس Set-Cookie RAW يدويًا باستخدام Headers.raw() . هذا هو واجهة node-fetch فقط.
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' ) ;
// Returns an array of values, instead of a string of comma-separated values
console . log ( response . headers . raw ( ) [ 'set-cookie' ] ) ; import fetch , {
Blob ,
blobFrom ,
blobFromSync ,
File ,
fileFrom ,
fileFromSync ,
} from 'node-fetch'
const mimetype = 'text/plain'
const blob = fileFromSync ( './input.txt' , mimetype )
const url = 'https://httpbin.org/post'
const response = await fetch ( url , { method : 'POST' , body : blob } )
const data = await response . json ( )
console . log ( data )يأتي Node-Fetch مع تطبيقات FormData متوافقة
import fetch , { FormData , File , fileFrom } from 'node-fetch'
const httpbin = 'https://httpbin.org/post'
const formData = new FormData ( )
const binary = new Uint8Array ( [ 97 , 98 , 99 ] )
const abc = new File ( [ binary ] , 'abc.txt' , { type : 'text/plain' } )
formData . set ( 'greeting' , 'Hello, world!' )
formData . set ( 'file-upload' , abc , 'new name.txt' )
const response = await fetch ( httpbin , { method : 'POST' , body : formData } )
const data = await response . json ( )
console . log ( data )إذا كنت بحاجة إلى نشر دفق قادم من أي مكان تعسفي ، فيمكنك إلحاق نقطة أو عنصر يشبه ملف.
الحد الأدنى للمتطلبات هو أن لديها:
Symbol.toStringTag Blob Filestream() أو طريقة arrayBuffer() التي تُرجع arraybuffer. يجب أن يعيد stream() أي كائن غير متزامن طالما أنه ينتج عن uint8array (أو المخزن المؤقت) ، لذلك تعمل تدفقات القراءة والتيار WhatwG بشكل جيد.
formData . append ( 'upload' , {
[ Symbol . toStringTag ] : 'Blob' ,
size : 3 ,
* stream ( ) {
yield new Uint8Array ( [ 97 , 98 , 99 ] )
} ,
arrayBuffer ( ) {
return new Uint8Array ( [ 97 , 98 , 99 ] ) . buffer
}
} , 'abc.txt' ) يمكنك إلغاء الطلبات باستخدام AbortController . التنفيذ المقترح هو abort-controller .
مثال على توقيت طلب بعد 150 مللي ثانية يمكن تحقيق ما يلي:
import fetch , { AbortError } from 'node-fetch' ;
// AbortController was added in node v14.17.0 globally
const AbortController = globalThis . AbortController || await import ( 'abort-controller' )
const controller = new AbortController ( ) ;
const timeout = setTimeout ( ( ) => {
controller . abort ( ) ;
} , 150 ) ;
try {
const response = await fetch ( 'https://example.com' , { signal : controller . signal } ) ;
const data = await response . json ( ) ;
} catch ( error ) {
if ( error instanceof AbortError ) {
console . log ( 'request was aborted' ) ;
}
} finally {
clearTimeout ( timeout ) ;
}انظر حالات الاختبار لمزيد من الأمثلة.
url سلسلة تمثل عنوان URL للجلبoptions خيارات طلب HTTP (S)Promise<Response>أداء HTTP (S) جلب.
يجب أن يكون url عنوان URL مطلقًا ، مثل https://example.com/ . سيؤدي عنوان URL للمرتبط بالمسار ( /file/under/root ) أو عنوان URL للبروتوكول ( //can-be-http-or-https.com/ ) إلى Promise مرفوض.
يتم عرض القيم الافتراضية بعد كل مفتاح خيار.
{
// These properties are part of the Fetch Standard
method : 'GET' ,
headers : { } , // Request headers. format is the identical to that accepted by the Headers constructor (see below)
body : null , // Request body. can be null, or a Node.js Readable stream
redirect : 'follow' , // Set to `manual` to extract redirect headers, `error` to reject redirect
signal : null , // Pass an instance of AbortSignal to optionally abort requests
// The following properties are node-fetch extensions
follow : 20 , // maximum redirect count. 0 to not follow redirect
compress : true , // support gzip/deflate content encoding. false to disable
size : 0 , // maximum response body size in bytes. 0 to disable
agent : null , // http(s).Agent instance or function that returns an instance (see below)
highWaterMark : 16384 , // the maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource.
insecureHTTPParser : false // Use an insecure HTTP parser that accepts invalid HTTP headers when `true`.
} إذا لم يتم تعيين قيم ، فسيتم إرسال رؤوس الطلب التالية تلقائيًا:
| رأس | قيمة |
|---|---|
Accept-Encoding | gzip, deflate, br (عندما options.compress === true |
Accept | */* |
Content-Length | (محسوبة تلقائيًا ، إن أمكن) |
Host | (معلومات المضيف والمنفذ من URI الهدف) |
Transfer-Encoding | chunked (عندما يكون req.body دفقًا) |
User-Agent | node-fetch |
ملاحظة: عندما يكون body Stream ، لا يتم تعيين Content-Length تلقائيًا.
يتيح لك خيار agent تحديد الخيارات المتعلقة بالشبكات والتي هي خارج نطاق الجلب ، بما في ذلك ولا يقتصر على ما يلي:
انظر http.Agent لمزيد من المعلومات.
إذا لم يتم تحديد أي وكيل ، يتم استخدام الوكيل الافتراضي الذي توفره Node.js. لاحظ أن هذا قد تغير في Node.js 19 للحصول على keepalive بشكل افتراضي. إذا كنت ترغب في تمكين keepalive في إصدار سابق من Node.js ، فيمكنك تجاوز الوكيل وفقًا لعينة الكود التالية.
بالإضافة إلى ذلك ، يقبل خيار agent وظيفة تُرجع http (S) .Agent العجلة المعطى عنوان URL الحالي ، وهذا مفيد أثناء سلسلة إعادة التوجيه عبر بروتوكول HTTP و HTTPS.
import http from 'node:http' ;
import https from 'node:https' ;
const httpAgent = new http . Agent ( {
keepAlive : true
} ) ;
const httpsAgent = new https . Agent ( {
keepAlive : true
} ) ;
const options = {
agent : function ( _parsedURL ) {
if ( _parsedURL . protocol == 'http:' ) {
return httpAgent ;
} else {
return httpsAgent ;
}
}
} ; يحتوي الدفق على Node.js على حجم مخزن مؤقت داخلي أصغر (16 كيلو بايت ، ويعرف أيضًا باسم highWaterMark ) من متصفحات من جانب العميل (> 1 ميجابايت ، غير متسقة عبر المتصفحات). ولهذا السبب ، عندما تكتب تطبيقًا متساوي الشكل واستخدام res.clone() ، فإنه سوف يتم تعليقه مع استجابة كبيرة في العقدة.
الطريقة الموصى بها لإصلاح هذه المشكلة هي حل الاستجابة المستنسخة بالتوازي:
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' ) ;
const r1 = response . clone ( ) ;
const results = await Promise . all ( [ response . json ( ) , r1 . text ( ) ] ) ;
console . log ( results [ 0 ] ) ;
console . log ( results [ 1 ] ) ; إذا كنت لا تحب الحل أعلاه لسبب ما ، فأنت قادرة على تعديل خيار highWaterMark لخيار 3.x :
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' , {
// About 1MB
highWaterMark : 1024 * 1024
} ) ;
const result = await res . clone ( ) . arrayBuffer ( ) ;
console . dir ( result ) ; انتقل إلى خيار insecureHTTPParser على http (s) .request. انظر http.request لمزيد من المعلومات.
يختلف خيار redirect: 'manual' لـ Node-Betch عن المتصفح والمواصفات ، مما يؤدي إلى استجابة مصطفة معتمدة. يمنحك Node-Fetch الاستجابة الأساسية التي تمت تصفيتها بدلاً من ذلك.
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/status/301' , { redirect : 'manual' } ) ;
if ( response . status === 301 || response . status === 302 ) {
const locationURL = new URL ( response . headers . get ( 'location' ) , response . url ) ;
const response2 = await fetch ( locationURL , { redirect : 'manual' } ) ;
console . dir ( response2 ) ;
}طلب HTTP (S) يحتوي على معلومات حول عنوان URL ، والطريقة ، والرؤوس ، والجسم. هذه الفئة تنفذ واجهة الجسم.
نظرًا لطبيعة Node.js ، لا يتم تنفيذ الخصائص التالية في هذه اللحظة:
typedestinationmodecredentialscacheintegritykeepaliveيتم توفير خصائص امتداد Node-Fetch التالية:
followcompresscounteragenthighWaterMarkانظر خيارات المعنى الدقيق لهذه الامتدادات.
(متوافق مع المواصفات)
input سلسلة تمثل عنوان URL ، أو Request آخر (والذي سيتم استنساخه)options خيارات طلب HTTP (S) يبني كائن Request جديد. المنشئ مطابق لتلك الموجودة في المتصفح.
في معظم الحالات ، يكون fetch(url, options) أبسط من إنشاء كائن Request .
استجابة HTTP (S). هذه الفئة تنفذ واجهة الجسم.
لا يتم تنفيذ الخصائص التالية في Node-Betch في هذه اللحظة:
trailer(متوافق مع المواصفات)
body String أو دفق Readableoptions قاموس خيارات ResponseInit يبني كائن Response جديد. المنشئ مطابق لتلك الموجودة في المتصفح.
نظرًا لأن Node.js لا تنفذ عمال الخدمة (الذي تم تصميم هذا الفصل) ، نادراً ما يتعين على أحدهم بناء Response مباشرة.
(متوافق مع المواصفات)
خاصية الراحة التي تمثل ما إذا كان الطلب قد انتهى بشكل طبيعي. سيتم تقييمها إلى صحيح إذا كانت حالة الاستجابة أكبر من أو تساوي 200 ولكن أصغر من 300.
(متوافق مع المواصفات)
خاصية الراحة التي تمثل ما إذا كان قد تم إعادة توجيه الطلب مرة واحدة على الأقل. سيتم تقييمه إلى صحيح إذا كان عداد إعادة التوجيه الداخلي أكبر من 0.
(الانحراف عن المواصفات)
خاصية الراحة التي تمثل نوع الاستجابة. يدعم Node-Petch 'default' و 'error' فقط ولا يستفيد من الاستجابات المصفاة.
يتيح هذا الفصل التلاعب والتكرار على مجموعة من رؤوس HTTP. يتم تنفيذ جميع الطرق المحددة في معيار الجلب.
(متوافق مع المواصفات)
init لشراء كائن Headers مسبقًا بناء كائن Headers جديد. يمكن أن يكون init إما null أو كائنًا Headers أو كائن خريطة قيمة المفاتيح أو أي كائن أمر غير قابل للارتداء.
// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
import { Headers } from 'node-fetch' ;
const meta = {
'Content-Type' : 'text/xml'
} ;
const headers = new Headers ( meta ) ;
// The above is equivalent to
const meta = [ [ 'Content-Type' , 'text/xml' ] ] ;
const headers = new Headers ( meta ) ;
// You can in fact use any iterable objects, like a Map or even another Headers
const meta = new Map ( ) ;
meta . set ( 'Content-Type' , 'text/xml' ) ;
const headers = new Headers ( meta ) ;
const copyOfHeaders = new Headers ( headers ) ; Body هو واجهة مجردة مع طرق قابلة للتطبيق على كل من فئات Request Response .
(الانحراف عن المواصفات)
Readable يتم تغليف البيانات في كائن Body . لاحظ أنه على الرغم من أن معيار الجلب يتطلب أن يكون الخاصية دائمًا عبارة عن دفق ReadableStream Readable في Node.js.
(متوافق مع المواصفات)
Booleanخاصية منطقية إذا تم استهلاك هذه الهيئة. وفقًا للمواصفات ، لا يمكن استخدام الجسم المستهلك مرة أخرى.
يأتي fetch مع طرق لتحليل حمولات multipart/form-data بالإضافة إلى أجسام x-www-form-urlencoded باستخدام .formData() هذا يأتي من فكرة أن عامل الخدمة يمكنه اعتراض هذه الرسائل قبل إرسالها إلى الخادم لتغييرها. هذا مفيد لأي شخص يقوم ببناء خادم حتى تتمكن من استخدامه لتحليل واستهلاك الحمولات.
import http from 'node:http'
import { Response } from 'node-fetch'
http . createServer ( async function ( req , res ) {
const formData = await new Response ( req , {
headers : req . headers // Pass along the boundary value
} ) . formData ( )
const allFields = [ ... formData ]
const file = formData . get ( 'uploaded-files' )
const arrayBuffer = await file . arrayBuffer ( )
const text = await file . text ( )
const whatwgReadableStream = file . stream ( )
// other was to consume the request could be to do:
const json = await new Response ( req ) . json ( )
const text = await new Response ( req ) . text ( )
const arrayBuffer = await new Response ( req ) . arrayBuffer ( )
const blob = await new Response ( req , {
headers : req . headers // So that `type` inherits `Content-Type`
} . blob ( )
} )(امتداد Node-Betch)
خطأ تشغيلي في عملية الجلب. انظر Error-Gandling.md لمزيد من المعلومات.
(امتداد Node-Betch)
خطأ يتم إلقاؤه عند إحباط الطلب استجابةً لحدث abort AbortSignal . لديها خاصية name AbortError . انظر Error-Gandling.md لمزيد من المعلومات.
نظرًا لأن أنواع 3.x يتم تجميعها باستخدام node-fetch ، لذلك لا تحتاج إلى تثبيت أي حزم إضافية.
بالنسبة للإصدارات القديمة ، يرجى استخدام تعريفات النوع من بالتأكيد:
npm install --save-dev @types/[email protected]بفضل Github/Fetch لتوفير مرجع تنفيذ قوي.
![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|
| ديفيد فرانك | جيمي ويرتينغ | أنتوني كيبينسكي | ريتشي بيندال | جريجور مارتينوس |
معهد ماساتشوستس للتكنولوجيا