本篇文檔是參考SuperAgent英文文檔翻譯整理成的。前段時間,在一個爬蟲項(xiàng)目中用到了SuperAgent,因?yàn)橛龅搅艘恍┛?,就詳?xì)地查閱了一番官方文檔,后為便于朋友查閱參考,我將翻譯的文檔進(jìn)行了簡要整理。后期,我還會針對SuperAgent使用中遇到的一些問題進(jìn)行完善,并附于文末Issue章節(jié)。同時也歡迎大家分享自己在使用SuperAgent過程中遇到的一些問題和解決方法。
1 簡介
SuperAgent是一個輕量級、靈活的、易讀的、低學(xué)習(xí)曲線的客戶端請求代理模塊,使用在NodeJS環(huán)境中。
官方文檔:http://visionmedia.github.io/superagent
使用示例:
var request = require('superagent')
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.then(res => {
alert('yay got ' + JSON.stringify(res.body));
});
在后面的講解中我們都使用request表示superagent對象,代碼中也省略如下部分:
var request = require('superagent')
2 請求
通過調(diào)用request對象then()或end()方法,或使用await關(guān)鍵字,發(fā)送一個請求。
request
.get('/search')
.then(res => {
// res.body, res.headers, res.status
})
.catch(err => {
// err.message, err.response
});
請求的方法類型(DELETE,HEAD,PATCH,POST和PUT)可以通過如下字符串來指定:
// 指定使用GET方法
request('GET', '/search')
.then(function (response) {
// success
}, function (error) {
// failure
});
也可以使用end()方法
request('GET', '/search')
.end(function(error, response){
if (response.ok) {
}
});
可以使用完整的URLs,由于同源策略的原因,這需要服務(wù)器實(shí)現(xiàn)了跨域訪問。
request
.get('https://example.com/search')
.then(res => {
});
除了上述使用的GET方法外,也可以使用DELETE,HEAD,PATCH,POST和PUT方法,只需要簡單地更改一下方法的名稱。
request
.head('/favicon.ico')
.then(response => {
});
在舊版本IE瀏覽器中delete是系統(tǒng)的關(guān)鍵字,為了兼容這一點(diǎn),可以調(diào)用del()方法來避免沖突。
request
.del('/book/1')
.end(function(response){
});
request默認(rèn)使用GET方法發(fā)送請求,可以簡寫成如下:
request('/search', (error, response) => {
});
3 HTTP/2
如果要使用HTTP/2協(xié)議發(fā)送請求,可以調(diào)用http2()方法。目前還暫不支持對服務(wù)器 HTTP/2能力的檢測。
const request = require('superagent');
const res = await request
.get('https://example.com/h2')
.http2();
4 設(shè)置頭部字段
報(bào)文header字段設(shè)置通過調(diào)用set()方法。
request
.get('/search')
.set('API-Key', 'foobar')
.set('Accept', 'application/json')
.then(callback);
你也可以傳遞一個對象來設(shè)置多個字段:
request
.get('/search')
.set({
'API-Key': 'foobar',
' Accept': 'application/json'
})
.then(callback);
5 GET請求
當(dāng)我們使用GET請求傳遞查詢字符串的時候,可以使用query()方法,同時傳遞一個對象作為參數(shù),下面的代碼將產(chǎn)生一個URL為/search?query=Manny&range=1..5&order=desc請求:
request
.get('/search')
.query({ query: 'Manny' })
.query({ range: '1..5' })
.query({ order: 'desc' })
.then(response => {
});
或者傳遞一個對象
request
.get('/search')
.query({
query: 'Manny',
range: '1..5',
order: 'desc'
})
.then(response => {
});
query()也接受一個字符串作為參數(shù)
request
.get('/querystring')
.query('search=Manny&range=1..5')
.then(response => {
})
參數(shù)拼接字符&也可以用下面的方式替代:
request
.get('/querystring')
.query('search=Manny')
.query('range=1..5')
.then(response => {
});
6 HEAD請求
query()方法也可以用于HEAD請求,下面的代碼將會產(chǎn)生一個URL為 /users?email=joe@smith.com的請求:
request
.head('/users')
.query({
email: 'joe@smith.com'
})
.then(response => {
});
7 POST / PUT請求
一個典型的JSON POST請求的代碼實(shí)現(xiàn)如下,設(shè)置相應(yīng)的Content-type頭字段,再寫入數(shù)據(jù)。在這個例子里,僅使用JSON字符串:
request.post('/user')
.set('Content-Type', 'application/json')
.send('{"name":"tj","pet":"tobi"}')
.then(callback)
JSON成為通用的數(shù)據(jù)格式后,request對象默認(rèn)Content-type類型就是application/json,因此代碼就可以簡化為:
request.post('/user')
.send('{"name":"tj","pet":"tobi"}')
.then(callback)
也可以多次調(diào)用send()方法完成
request.post('/user')
.send({ name: 'tj' })
.send({ pet: 'tobi' })
.then(callback
默認(rèn)情況下,發(fā)送字符串時Content-type會被設(shè)置為application/x-www-form-urlencoded,多次調(diào)用send()方法會使用&連接起來,下面的代碼中最終結(jié)果為:name=tj&pet=tobi
request.post('/user')
.send('name=tj')
.send('pet=tobi')
.then(callback);
SuperAgent請求的數(shù)據(jù)格式是可以擴(kuò)展的,不過默認(rèn)支持“form”和“json”兩種格式,想要以application/x-www-form-urlencoded格式發(fā)送數(shù)據(jù)的話,則可以調(diào)用type()方法并傳入'form'參數(shù),這里默認(rèn)的參數(shù)是“json”。下面的請求中,POST請求體為name=tj&pet=tobi。
request.post('/user')
.type('form')
.send({ name: 'tj' })
.send({ pet: 'tobi' })
.then(callback)
支持發(fā)送FormData對象。下面的例子中發(fā)送id="myForm"的<form>表單數(shù)據(jù):
request.post('/user')
.send(new FormData(document.getElementById('myForm')))
.then(callback)
提示:FormData類型其實(shí)是在XMLHttpRequest 2級定義的,它是為序列化表以及創(chuàng)建與表單格式相同的數(shù)據(jù)(當(dāng)然是用于XHR傳輸)提供便利。
8 Content-Type設(shè)置
通常使用set()方法
request.post('/user')
.set('Content-Type', 'application/json')
簡便的方法是調(diào)用.type()方法,傳遞一個規(guī)范的MIME名稱,包括type/subtype,或者一個簡單的后綴就像xml,json,png這樣。例如:
request.post('/user')
.type('application/json')
request.post('/user')
.type('json')
request.post('/user')
.type('png')
9 序列化請求體
SuperAgent會自動序列化JSON和表單數(shù)據(jù),你也可以為其他類型設(shè)置自動序列化:
request.serialize['application/xml'] = function (obj) {
return 'string generated from obj';
};
// going forward, all requests with a Content-type of
// 'application/xml' will be automatically serialized
如果你希望以自定義格式發(fā)送數(shù)據(jù),可以通過.serialize()方法為每個請求設(shè)置相應(yīng)的序列化方法,以替換內(nèi)置序列化方法:
request
.post('/user')
.send({foo: 'bar'})
.serialize(obj => {
return 'string generated from obj';
});
10 重發(fā)請求
當(dāng)給定retry()方法時,SuperAgent將自動重試請求,如果它們以短暫的方式失敗或者可能由于因特網(wǎng)連接不正常而失敗。
這個方法有兩個可選參數(shù):重試次數(shù)(默認(rèn)值3)和回調(diào)函數(shù)。它在每次重發(fā)之前調(diào)用回調(diào)(error, res)?;卣{(diào)可以返回true/false,以決定是否要重發(fā)請求。
request
.get('https://example.com/search')
.retry(2) // or:
.retry(2, callback)
.then(finished);
需要注意的是:應(yīng)該只對HTTP等冪請求使用retry()方法(即,到達(dá)服務(wù)器的多個請求不會導(dǎo)致不希望的副作用,如重復(fù)購買,否則會產(chǎn)生多個訂單)。
11 設(shè)置Accept
與type()方法一樣,這里可以調(diào)用accept()方法來設(shè)置Accept接受類型,這個值將會被request.types所引用,支持傳遞一個規(guī)范的MIME名稱,包括type/subtype,或者一個簡單的后綴:xml,json,``png等。例如:
request.get('/user')
.accept('application/json')
request.get('/user')
.accept('json')
request.post('/user')
.accept('png')
Facebook和接收J(rèn)SON:如果你是在調(diào)用Facebook的API,確保請求頭中Accept: application/json 。否則,Facebook 將返回Content-Type: text/javascript; charset=UTF-8響應(yīng), SuperAgent將不會解析這個響應(yīng),讀取響應(yīng)體會得到undefined。你需要在請求對象request加上request.accept('json')或者request.header('Accept', 'application/json')代碼。
12 查詢字符串
調(diào)用.query()方法可以自動生成查詢字符串,比如向URL為?format=json&dest=/login發(fā)送一個post請求:
request
.post('/')
.query({ format: 'json' })
.query({ dest: '/login' })
.send({ post: 'data', here: 'wahoo' })
.then(callback);
默認(rèn)情況下,查詢字符串的拼裝是沒有特定的順序。調(diào)用sortQuery()方法將默認(rèn)按照ASCII碼順序進(jìn)行,你也可以傳遞一個比較函數(shù)來指定排序規(guī)則,比較函數(shù)需要傳遞兩個參數(shù)(在回調(diào)過程中會自動傳遞進(jìn)兩個參數(shù),這兩個參數(shù)就是用于比較的查詢字符串),返回值是正整數(shù)、負(fù)整數(shù)或者0。
// 選擇默認(rèn)排序
request.get('/user')
.query('name=Nick')
.query('search=Manny')
.sortQuery()
.then(callback)
// 客制化的排序函數(shù)
request.get('/user')
.query('name=Nick')
.query('search=Manny')
.sortQuery((a, b) => a.length - b.length)
.then(callback)
上述客制化的排序函數(shù)中,a和b實(shí)際上就是sortQuery()回調(diào)過程中傳遞進(jìn)去的兩個查詢字符串,按照查詢字符串長度來排序的,長度大的排在前面。
13 TLS選項(xiàng)
在Node.js中使用SuperAgent,支持對HTTPS請求的下列配置:
-
ca():將CA證書設(shè)置為信任 -
cert():設(shè)置客戶端證書鏈 -
key(): 設(shè)置客戶端私鑰 -
pfx(): 設(shè)置客戶端PFX或PKCS12編碼的私鑰和證書鏈
更多信息可以查看:https.request 官方文檔.
var key = fs.readFileSync('key.pem'),
cert = fs.readFileSync('cert.pem');
request
.post('/client-auth')
.key(key)
.cert(cert)
.then(callback);
var ca = fs.readFileSync('ca.cert.pem');
request
.post('https://localhost/private-ca-server')
.ca(ca)
.then(res => {});
14 解析響應(yīng)體
SuperAgent 可以解析常用的響應(yīng)體,目前支持application/x-www-form-urlencoded,application/json, 和multipart/form-data格式。如下代碼,你也可以對其它類型的響應(yīng)體設(shè)置相應(yīng)的解析方法:
// 瀏覽器端使用SuperAgent
request.parse['application/xml'] = function (str) {
return {'object': 'parsed from str'};
};
// Node中使用SuperAgent
request.parse['application/xml'] = function (res, cb) {
// 解析響應(yīng)內(nèi)容,設(shè)置響應(yīng)體代碼
cb(null, res);
};
// 自動解析響應(yīng)體
通過調(diào)用buffer(true)和parse(fn)的配合,你可以設(shè)置一個定制的解析器(定制的解析器優(yōu)先于內(nèi)置解析器)。 如果沒有啟用響應(yīng)緩沖(buffer(false)),那么響應(yīng)事件的觸發(fā)將不會等待主體解析器完成,因此響應(yīng)體將不可用。
14.1 JSON/Urlencoded
response.body是解析后的內(nèi)容對象,比如對于一個請求響應(yīng)'{"user":{"name":"tobi"}}'字符串,response.body.user.name會返回"tobi"。同樣的,與x-www-form-urlencoded格式的"user[name]=tobi"解析后值也是一樣,只支持嵌套的一個層次,如果需要更復(fù)雜的數(shù)據(jù),請使用JSON格式。
數(shù)組會以重復(fù)鍵名的方式進(jìn)行發(fā)送,send({color: ['red','blue']})會發(fā)送"color=red&color=blue"。如果你希望數(shù)組鍵的名稱包含"[]",則需要自己添加,SuperAgent是不會自動添加。
14.2 Multipart
Node客戶端通過Formidable模塊來支持multipart/form-data類型,當(dāng)解析一個multipart響應(yīng)時,response.files屬性就可以用。假設(shè)一個請求響應(yīng)得到下面的數(shù)據(jù):
--whoop
Content-Disposition: attachment; name="image"; filename="tobi.png"
Content-Type: image/png
... data here ...
--whoop
Content-Disposition: form-data; name="name"
Content-Type: text/plain
Tobi
--whoop--
你可以獲取到res.body.name名為’Tobi’,res.files.image為一個file對象,包括一個磁盤文件路徑、文件名稱,還有其它的文件屬性。
14.3 Binary
在瀏覽器中可以使用responseType('blob')來請求處理二進(jìn)制格式的響應(yīng)體。在Node.js中運(yùn)行此API是不必要的。此方法的支持參數(shù)值為:
-
'blob':會被傳遞為XmlHTTPRequest的responseType屬性。 -
'arraybuffer':會被傳遞為XmlHTTPRequest的responseType屬性。
req.get('/binary.data')
.responseType('blob')
.then(res => {
// res.body will be a browser native Blob type here
});
更多的信息可以查看:xhr.responseType 文檔.
15 響應(yīng)對象屬性
SuperAgent請求得到響應(yīng)后,響應(yīng)對象的屬性主要有:
text:未解析前的響應(yīng)內(nèi)容,字符串類型。一般只在mime類型能夠匹配"text/","json","x-www-form-urlencoding"的情況下,這個屬性才會有效,默認(rèn)為nodejs客戶端提供;body:響應(yīng)數(shù)據(jù)解析后的對象,對象類型。header:解析之后的響應(yīng)頭數(shù)據(jù),數(shù)組類型。type:響應(yīng)報(bào)文的Content-Type值,字符串類型。charset:響應(yīng)的字符集,字符串類型。status:響應(yīng)狀態(tài)標(biāo)識。statusCode:響應(yīng)的狀態(tài)碼,數(shù)整數(shù)類型。如:200、302、404、500等。
15.1 text
response.text包含未解析前的響應(yīng)內(nèi)容,一般只在mime類型能夠匹配"text/","json","x-www-form-urlencoding"的情況下,這個屬性才會有效,默認(rèn)為nodejs客戶端提供,這是出于節(jié)省內(nèi)存的考慮。因?yàn)榫彌_大數(shù)據(jù)量的文本(如multipart文件或圖像)的效率非常低。要強(qiáng)制緩沖,請參閱“響應(yīng)緩沖”部分。
15.2 body
與SuperAgent請求數(shù)據(jù)自動序列化一樣,響應(yīng)數(shù)據(jù)也會自動的解析,當(dāng)為一個Content-Type定義一個解析器后,就能自動解析,默認(rèn)解析包含application/json和application/x-www-form-urlencoded,可以通過response.body來訪問解析對象.
15.3 header fields
response.header包含解析之后的響應(yīng)頭數(shù)據(jù),字段值都是Node處理成小寫字母形式,如response.header['content-length']。
15.4 Content-Type
Content-Type響應(yīng)頭字段是一個特列,服務(wù)器提供response.type來訪問它,默認(rèn)response.charset是空的(如果有的話,則為指定類型),例如Content-Type值為"text/html; charset=utf8",則response.type為text/html,response.charset為"utf8"。
15.5 status
響應(yīng)狀態(tài)標(biāo)識可以用來判斷請求是否成功,除此之外,可以用SuperAgent來構(gòu)建理想的RESTful服務(wù)器,這些標(biāo)識目前定義為:
var type = status / 100 | 0;
// status / class
res.status = status;
res.statusType = type;
// basics
res.info = 1 == type;
res.ok = 2 == type;
res.clientError = 4 == type;
res.serverError = 5 == type;
res.error = 4 == type || 5 == type;
// sugar
res.accepted = 202 == status;
res.noContent = 204 == status || 1223 == status;
res.badRequest = 400 == status;
res.unauthorized = 401 == status;
res.notAcceptable = 406 == status;
res.notFound = 404 == status;
res.forbidden = 403 == status;
16.中止請求
可以通過req.abort()來中止請求。
17.請求超時
有時網(wǎng)絡(luò)和服務(wù)器會“卡住”,并且在接受請求后從不響應(yīng)。設(shè)置超時以避免請求永遠(yuǎn)等待。
req.timeout({deadline:ms})或req.timeout(ms): ms是大于0的毫秒數(shù)。為整個請求設(shè)置一個截止時間(包括所有上傳、重定向、服務(wù)器處理時間)完成。如果在那個時間內(nèi)沒有得到完整的響應(yīng),請求將被中止。req.timeout({response:ms}):設(shè)置等待第一個字節(jié)從服務(wù)器到達(dá)的最大時間,但不限制整個下載可以消耗多長時間。響應(yīng)超時應(yīng)該比服務(wù)器響應(yīng)的時間長至少幾秒鐘,因?yàn)樗€包括進(jìn)行DNS查找、TCP/IP和TLS連接的時間,以及上傳請求數(shù)據(jù)的時間。
你應(yīng)該同時使用deadline和response超時。通過這種方式,你可以通過較短的response超時來快速檢測無響應(yīng)網(wǎng)絡(luò),并且使用較長的deadline來在緩慢但可靠的網(wǎng)絡(luò)上提供一個合適的時間。注意,這兩個計(jì)時器都限制了上傳文件的上傳時間。如果上傳文件,則使用長時間超時。
request
.get('/big-file?network=slow')
.timeout({
response: 5000, // Wait 5 seconds for the server to start sending,
deadline: 60000, // but allow 1 minute for the file to finish loading.
})
.then(res => {
/* responded in time */
}, err => {
if (err.timeout) { /* timed out! */ } else { /* other error */ }
});
超時錯誤會提供一個timeout屬性。
18.認(rèn)證
Node和瀏覽器中都可以通過auth()方法來完成認(rèn)證。
request
.get('http://local')
.auth('tobi', 'learnboost')
.then(callback);
nodejs客戶端也可以通過傳遞一個像下面這樣的URL:
request.get('http://tobi:learnboost@local').then(callback);
默認(rèn)在瀏覽器中只使用基本的認(rèn)證方式,你也可以添加{type:'auto'},以啟用瀏覽器中內(nèi)置的所有方法(摘要、NTLM等):
request.auth('digest', 'secret', {type:'auto'})
19.跟隨重定向
默認(rèn)是向上跟隨5個重定向,可以通過調(diào)用.res.redirects(n)來設(shè)置個數(shù):
request
.get('/some.png')
.redirects(2)
.then(callback);
20.全局狀態(tài)代理
20.1 保存cookies
在Node SuperAgent中,默認(rèn)情況下不保存cookie,但是可以使用.agent()方法創(chuàng)建一個含有cookie的SuperAgent副本。每個副本都有一個單獨(dú)的cookie數(shù)據(jù)。
const agent = request.agent();
agent
.post('/login')
.then(() => {
return agent.get('/cookied-page');
});
在瀏覽器中,cookie由瀏覽器自動管理,因此.agent()不會格式化處理cookies。
20.2 多請求的默認(rèn)選項(xiàng)
使用agent進(jìn)行的多個請求中,agent調(diào)用的常規(guī)方法也將默認(rèn)用于agent的后續(xù)所有的請求中。這些常規(guī)方法包括:use, on, once, set, query, type, accept, auth, withCredentials, sortQuery, retry, ok, redirects, timeout, buffer, serialize, parse, ca, key, pfx, cert。
const agent = request.agent()
.use(plugin)
.auth(shared);
await agent.get('/with-plugin-and-auth');
await agent.get('/also-with-plugin-and-auth');
21.管道數(shù)據(jù)
在nodejs客戶端中,可以使用一個請求流來傳輸數(shù)據(jù)。需要注意的是:用pipe()取代了end()和then()方法。
下面是將文件內(nèi)容作為請求進(jìn)行管道傳輸例子:
const request = require('superagent');
const fs = require('fs');
const stream = fs.createReadStream('path/to/my.json');
const req = request.post('/somewhere');
req.type('json');
stream.pipe(req);
注意,在管道傳輸?shù)秸埱髸r,superagent使用分塊傳輸編碼發(fā)送管道數(shù)據(jù),這不是所有服務(wù)器(例如Python WSGI服務(wù)器)都支持的。
下面是輸送一個響應(yīng)流到文件的管道傳輸例子:
const stream = fs.createWriteStream('path/to/my.json');
const req = request.get('/some.json');
req.pipe(stream);
不能將管道、回調(diào)或promise混合在一起使用,不能嘗試對end()或response對象進(jìn)行管道操作(pipe()),如下所示:
// 不能做下面的操作
const stream = getAWritableStream();
const req = request
.get('/some.json')
// BAD: this pipes garbage to the stream and fails in unexpected ways
.end((err, this_does_not_work) => this_does_not_work.pipe(stream))
const req = request
.get('/some.json')
.end()
// BAD: this is also unsupported, .pipe calls .end for you.
.pipe(nope_its_too_late);
22.Multipart/form-data請求
superagen提供了attach() 和 field()方法用于構(gòu)建multipart/form-data請求。
當(dāng)你使用了field()或者attach(),你就不能使用 send()方法,你也不能設(shè)置 Content-Type (superagen會自動設(shè)置糾正后的type)。
22.1 附件
可以使用attach(name, [file], [options])進(jìn)行文件發(fā)送。你可以通過多次調(diào)用attach()附加多個文件。attach()的參數(shù)說明如下:
-
name:文件名 -
file:文件路徑字符串,或Blob/Buffer對象。 -
options:(可選)字符串或自定義文件名或{filename: string}對象。在Node中也支持{contentType: 'mime/type'}。在瀏覽器中創(chuàng)建一個具有適當(dāng)類型的Blob。
request
.post('/upload')
.attach('image1', 'path/to/felix.jpeg')
.attach('image2', imageBuffer, 'luna.jpeg')
.field('caption', 'My cats')
.then(callback);
22.2 字段值
與HTML中表單的字段類似,你可以調(diào)用field(name,value)方法來設(shè)置字段,假設(shè)你想上傳一個圖片的并附帶自己的名稱和郵箱,那么你可以像下面這樣:
request
.post('/upload')
.field('user[name]', 'Tobi')
.field('user[email]', 'tobi@learnboost.com')
.field('friends[]', ['loki', 'jane'])
.attach('image', 'path/to/tobi.png')
.then(callback);
23.壓縮
NodeJS客戶端本身就提供壓縮響應(yīng)內(nèi)容,所以你不需要做任何其它處理。
24.響應(yīng)緩沖
為了強(qiáng)制緩沖response.text這樣未解析前的響應(yīng)內(nèi)容(一般只在mime類型能夠匹配"text/","json","x-www-form-urlencoding"的情況下才進(jìn)行緩沖),可以調(diào)用buffer()方法,想取消默認(rèn)的文本緩沖響應(yīng)像text/plain, text/html這樣的,可以調(diào)用buffer(false)方法。
// 強(qiáng)制緩沖
request
.get('/userinfo')
.buffer(true)
.then(callback)
// 取消緩沖
request
.get('/userinfo')
.buffer(false)
.then(callback)
當(dāng)緩沖response.buffered標(biāo)識有效了,那么就可以在一個回調(diào)函數(shù)里處理緩沖和未緩沖的響應(yīng).
25.跨域資源共享(CORS)
出于安全原因,瀏覽器將阻止跨源請求,除非服務(wù)器使用CORS頭進(jìn)行選擇。瀏覽器還將做出額外的選項(xiàng)請求,以檢查服務(wù)器允許的HTTP頭和方法。更多信息可參閱:CORS.
withCredentials()方法可以激活發(fā)送原始cookie的能力,不過只有在Access-Control-Allow-Origin不是一個通配符(*),并且Access-Control-Allow-Credentials為’true’的情況下才行。
request
.get('https://api.example.com:4001/')
.withCredentials()
.then(res => {
assert.equal(200, res.status);
assert.equal('tobi', res.text);
})
26.錯誤處理
回調(diào)函數(shù)總是會傳遞兩個參數(shù):error 錯誤和response 響應(yīng)。如果沒有發(fā)生錯誤,第一個參數(shù)將為null。
request
.post('/upload')
.attach('image', 'path/to/tobi.png')
.then(response => {
});
你可以加入監(jiān)聽錯誤的代碼,錯誤產(chǎn)生之后會執(zhí)行監(jiān)聽代碼。
request
.post('/upload')
.attach('image', 'path/to/tobi.png')
.on('error', handle)
.then(response => {
});
注意:
superagent默認(rèn)情況下,對響應(yīng)4xx和5xx的認(rèn)為不是錯誤,例如當(dāng)響應(yīng)返回一個500或者403的時候,這些狀態(tài)信息可以通過response.error,response.status和其它的響應(yīng)屬性來查看。
不產(chǎn)生響應(yīng)的網(wǎng)絡(luò)故障、超時和其他錯誤將不包含response.error,response.status屬性。
如果希望處理404個或其他HTTP錯誤響應(yīng),可以查詢error.status屬性。當(dāng)發(fā)生HTTP錯誤(4xx或5xx響應(yīng))時,response.error屬性是error對象,這可以用來作以下檢查:
if (error && error.status === 404) {
alert('oh no ' + response.body.message);
}
else if (error) {
// all other error types we handle generically
}
或者,可以使用ok(callback)方法來判斷響應(yīng)是否是錯誤。對ok()的回調(diào)得到響應(yīng),如果響應(yīng)成功,則返回true。
request.get('/404')
.ok(res => res.status < 500)
.then(response => {
// reads 404 page as a successful response
})
27.進(jìn)度跟蹤
superagent在大型文件的上傳和下載過程中觸發(fā)progress事件。
request.post(url)
.attach('field_name', file)
.on('progress', event => {
/* the event is:
{
direction: "upload" or "download"
percent: 0 to 100 // may be missing if file size is unknown
total: // total file size, may be missing
loaded: // bytes downloaded or uploaded so far
} */
})
.then()
event屬性包括:
-
direction:upload或download -
percent:0到100,文件大小未知的話為無效 -
total:文件總大小,可能為無效 -
loaded: 已經(jīng)下載或上傳的字節(jié)數(shù)
28.Promise和Generator支持
SuperAgent的請求是一個“thenable”對象,它與JavaScript承諾和異步/等待語法兼容。
如果你正在使用promises,那么就不要再調(diào)用end()或pipe()方法。任何使用then()或者await操作都會禁用所有其他使用請求的方式。
像CO或類似KOA這樣的Web框架,可以在superagent使用yield:
const req = request
.get('http://local')
.auth('tobi', 'learnboost');
const res = yield req;
請注意,superagent期望全局promises對象存在。在Internet Explorer或Node.js 0.10中需要使用polyfill組件。
29.瀏覽器和Node版本
SuperAgent有兩個實(shí)現(xiàn):一個是用于web瀏覽器(使用XHR)的版本,另一個是用于Node.JS (使用核心的http模塊)版本。
30.3XX處理
HTTP 3XX是重定向報(bào)文,superagent默認(rèn)會自動跟蹤下去,我們也不能使用redirect(0)的方法來禁止重定向,因此需要使用原生的http來處理。
request.post({
url: '/login',
}, function (err, res, body) {
if (!err && (res.statusCode == 301 || res.statusCode == 302)) {
// 登錄成功后服務(wù)端返回重定位報(bào)文
cookie += ';' + res.headers['set-cookie']
res1.redirect('listall')
} else if (res.statusCode == 200) {
// 登錄失敗服務(wù)端會返回200
// ...
} else {
// 其他錯誤信息處理
console.log(err)
}
})
31.Issue
歡迎大家在文末評論區(qū)提出自己在使用過程中遇到的問題及其解決方法?。?!