SuperAgent使用文檔

本篇文檔是參考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,PATCHPOSTPUT)可以通過如下字符串來指定:

// 指定使用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,HEADPATCH,POSTPUT方法,只需要簡單地更改一下方法的名稱。

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ù)中,ab實(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':會被傳遞為XmlHTTPRequestresponseType屬性。
  • 'arraybuffer':會被傳遞為XmlHTTPRequestresponseType屬性。
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/jsonapplication/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.typetext/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)該同時使用deadlineresponse超時。通過這種方式,你可以通過較短的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.errorresponse.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屬性包括:

  • directionuploaddownload
  • percent0100 ,文件大小未知的話為無效
  • 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ū)提出自己在使用過程中遇到的問題及其解決方法?。?!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容