怨爷 發表於 2020-3-30 23:58:00

[转] SuperAgent使用文档

<div>
<p>本篇文档是参考SuperAgent英文文档翻译整理成的。前段时间,在一个爬虫项目中用到了SuperAgent,因为遇到了一些坑,就详细地查阅了一番官方文档,后为便于朋友查阅参考,我将翻译的文档进行了简要整理。后期,我还会针对SuperAgent使用中遇到的一些问题进行完善,并附于文末Issue章节。同时也欢迎大家分享自己在使用SuperAgent过程中遇到的一些问题和解决方法。</p>
<h2>1 简介</h2>
<p>SuperAgent是一个轻量级、灵活的、易读的、低学习曲线的客户端请求代理模块,使用在NodeJS环境中。</p>
<p>官方文档:http://visionmedia.github.io/superagent</p>
<p>使用示例:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token keyword">var request <span class="token operator">= <span class="token function">require<span class="token punctuation">(<span class="token string">'superagent'<span class="token punctuation">)

request
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/api/pet'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">send<span class="token punctuation">(<span class="token punctuation">{ name<span class="token punctuation">: <span class="token string">'Manny'<span class="token punctuation">, species<span class="token punctuation">: <span class="token string">'cat' <span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">set<span class="token punctuation">(<span class="token string">'X-API-Key'<span class="token punctuation">, <span class="token string">'foobar'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">set<span class="token punctuation">(<span class="token string">'Accept'<span class="token punctuation">, <span class="token string">'application/json'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">res <span class="token operator">=&gt; <span class="token punctuation">{
   <span class="token function">alert<span class="token punctuation">(<span class="token string">'yay got ' <span class="token operator">+ <span class="token constant">JSON<span class="token punctuation">.<span class="token function">stringify<span class="token punctuation">(res<span class="token punctuation">.body<span class="token punctuation">)<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>在后面的讲解中我们都使用<code>request</code>表示<code>superagent</code>对象,代码中也省略如下部分:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token keyword">var request <span class="token operator">= <span class="token function">require<span class="token punctuation">(<span class="token string">'superagent'<span class="token punctuation">)
</span></span></span></span></span></span></code></pre>
</div>
<h2>2 请求</h2>
<p>通过调用<code>request</code>对象<code>then()</code>或<code>end()</code>方法,或使用<code>await</code>关键字,发送一个请求。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(res <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
   <span class="token comment">// res.body, res.headers, res.status
<span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token keyword">catch<span class="token punctuation">(err <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
   <span class="token comment">// err.message, err.response
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>请求的方法类型(<code>DELETE</code>,<code>HEAD</code>,<code>PATCH</code>,<code>POST</code>和<code>PUT</code>)可以通过如下字符串来指定:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token comment">// 指定使用GET方法
<span class="token function">request<span class="token punctuation">(<span class="token string">'GET'<span class="token punctuation">, <span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token keyword">function <span class="token punctuation">(<span class="token parameter">response<span class="token punctuation">) <span class="token punctuation">{
    <span class="token comment">// success

<span class="token punctuation">}<span class="token punctuation">,<span class="token keyword">function <span class="token punctuation">(<span class="token parameter">error<span class="token punctuation">) <span class="token punctuation">{
    <span class="token comment">// failure

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>也可以使用<code>end()</code>方法</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token function">request<span class="token punctuation">(<span class="token string">'GET'<span class="token punctuation">, <span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">end<span class="token punctuation">(<span class="token keyword">function<span class="token punctuation">(<span class="token parameter">error<span class="token punctuation">, response<span class="token punctuation">)<span class="token punctuation">{
    <span class="token keyword">if <span class="token punctuation">(response<span class="token punctuation">.ok<span class="token punctuation">) <span class="token punctuation">{
    <span class="token punctuation">}
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>可以使用完整的URLs,由于同源策略的原因,这需要服务器实现了跨域访问。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'https://example.com/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(res <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>除了上述使用的<code>GET</code>方法外,也可以使用<code>DELETE</code>,<code>HEAD</code>,<code>PATCH</code>,<code>POST</code>和<code>PUT</code>方法,只需要简单地更改一下方法的名称。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request
<span class="token punctuation">.<span class="token function">head<span class="token punctuation">(<span class="token string">'/favicon.ico'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">response <span class="token operator">=&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>在旧版本IE浏览器中<code>delete</code>是系统的关键字,为了兼容这一点,可以调用<code>del()</code>方法来避免冲突。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request
<span class="token punctuation">.<span class="token function">del<span class="token punctuation">(<span class="token string">'/book/1'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">end<span class="token punctuation">(<span class="token keyword">function<span class="token punctuation">(<span class="token parameter">response<span class="token punctuation">)<span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p><code>request</code>默认使用GET方法发送请求,可以简写成如下:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-tsx"><code class="language-tsx"><span class="token function">request<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">, <span class="token punctuation">(<span class="token parameter">error<span class="token punctuation">, response<span class="token punctuation">) <span class="token operator">=&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>3 HTTP/2</h2>
<p>如果要使用HTTP/2协议发送请求,可以调用<code>http2()</code>方法。目前还暂不支持对服务器 HTTP/2能力的检测。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">const request <span class="token operator">= <span class="token function">require<span class="token punctuation">(<span class="token string">'superagent'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const res <span class="token operator">= <span class="token keyword">await request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'https://example.com/h2'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">http2<span class="token punctuation">(<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>4 设置头部字段</h2>
<p>报文header字段设置通过调用<code>set()</code>方法。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token keyword">set<span class="token punctuation">(<span class="token string">'API-Key'<span class="token punctuation">, <span class="token string">'foobar'<span class="token punctuation">)
<span class="token punctuation">.<span class="token keyword">set<span class="token punctuation">(<span class="token string">'Accept'<span class="token punctuation">, <span class="token string">'application/json'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>你也可以传递一个对象来设置多个字段:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token keyword">set<span class="token punctuation">(<span class="token punctuation">{
   <span class="token string">'API-Key'<span class="token punctuation">: <span class="token string">'foobar'<span class="token punctuation">,
   <span class="token string">' Accept'<span class="token punctuation">: <span class="token string">'application/json'
    <span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>5 GET请求</h2>
<p>当我们使用GET请求传递查询字符串的时候,可以使用<code>query()</code>方法,同时传递一个对象作为参数,下面的代码将产生一个URL为<code>/search?query=Manny&amp;range=1..5&amp;order=desc</code>请求:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token punctuation">{ query<span class="token punctuation">: <span class="token string">'Manny' <span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token punctuation">{ range<span class="token punctuation">: <span class="token string">'1..5' <span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token punctuation">{ order<span class="token punctuation">: <span class="token string">'desc' <span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(response <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>或者传递一个对象</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token punctuation">{
    query<span class="token punctuation">: <span class="token string">'Manny'<span class="token punctuation">,
    range<span class="token punctuation">: <span class="token string">'1..5'<span class="token punctuation">,
    order<span class="token punctuation">: <span class="token string">'desc'
<span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(response <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p><code>query()</code>也接受一个字符串作为参数</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/querystring'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'search=Manny&amp;range=1..5'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(response <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>参数拼接字符<code>&amp;</code>也可以用下面的方式替代:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/querystring'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'search=Manny'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'range=1..5'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(response <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>6 HEAD请求</h2>
<p><code>query()</code>方法也可以用于HEAD请求,下面的代码将会产生一个URL为 <code>/users?email=joe@smith.com</code>的请求:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request
<span class="token punctuation">.<span class="token function">head<span class="token punctuation">(<span class="token string">'/users'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token punctuation">{
    email<span class="token punctuation">: <span class="token string">'joe@smith.com'
<span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">response <span class="token operator">=&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>7 POST / PUT请求</h2>
<p>一个典型的JSON POST请求的代码实现如下,设置相应的Content-type头字段,再写入数据。在这个例子里,仅使用JSON字符串:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-rust"><code class="language-rust">request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token lifetime-annotation symbol">'/user<span class="token lifetime-annotation symbol">')
<span class="token punctuation">.<span class="token function">set<span class="token punctuation">(<span class="token lifetime-annotation symbol">'Content-Type<span class="token lifetime-annotation symbol">', <span class="token lifetime-annotation symbol">'application/json<span class="token lifetime-annotation symbol">')
<span class="token punctuation">.<span class="token function">send<span class="token punctuation">(<span class="token lifetime-annotation symbol">'{<span class="token string">"name"<span class="token punctuation">:<span class="token string">"tj"<span class="token punctuation">,<span class="token string">"pet"<span class="token punctuation">:<span class="token string">"tobi"<span class="token punctuation">}<span class="token lifetime-annotation symbol">')
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>JSON成为通用的数据格式后,<code>request</code>对象默认Content-type类型就是<code>application/json</code>,因此代码就可以简化为:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-rust"><code class="language-rust">request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token lifetime-annotation symbol">'/user<span class="token lifetime-annotation symbol">')
<span class="token punctuation">.<span class="token function">send<span class="token punctuation">(<span class="token lifetime-annotation symbol">'{<span class="token string">"name"<span class="token punctuation">:<span class="token string">"tj"<span class="token punctuation">,<span class="token string">"pet"<span class="token punctuation">:<span class="token string">"tobi"<span class="token punctuation">}<span class="token lifetime-annotation symbol">')
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>也可以多次调用<code>send()</code>方法完成</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.post('/user')
.send({ name: 'tj' })
.send({ pet: 'tobi' })
.then(callback
</code></pre>
</div>
<p>默认情况下,发送字符串时<code>Content-type</code>会被设置为<code>application/x-www-form-urlencoded</code>,多次调用<code>send()</code>方法会使用<code>&amp;</code>连接起来,下面的代码中最终结果为:<code>name=tj&amp;pet=tobi</code></p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.post('/user')
.send('name=tj')
.send('pet=tobi')
.then(callback);
</code></pre>
</div>
<p><strong>SuperAgent</strong>请求的数据格式是可以扩展的,不过默认支持“form”和“json”两种格式,想要以application/x-www-form-urlencoded格式发送数据的话,则可以调用<code>type()</code>方法并传入<code>'form'</code>参数,这里默认的参数是“json”。下面的请求中,POST请求体为<code>name=tj&amp;pet=tobi</code>。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.post('/user')
.type('form')
.send({ name: 'tj' })
.send({ pet: 'tobi' })
.then(callback)
</code></pre>
</div>
<p>支持发送<code>FormData</code>对象。下面的例子中发送<code>id="myForm"</code>的<code>&lt;form&gt;</code>表单数据:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">send<span class="token punctuation">(<span class="token keyword">new <span class="token class-name">FormData<span class="token punctuation">(document<span class="token punctuation">.<span class="token function">getElementById<span class="token punctuation">(<span class="token string">'myForm'<span class="token punctuation">)<span class="token punctuation">)<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p><strong>提示:</strong><code>FormData</code>类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。</p>
<h2>8 Content-Type设置</h2>
<p>通常使用<code>set()</code>方法</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.post('/user')
.set('Content-Type', 'application/json')
</code></pre>
</div>
<p>简便的方法是调用<code>.type()</code>方法,传递一个规范的<code>MIME</code>名称,包括<code>type/subtype</code>,或者一个简单的后缀就像<code>xml</code>,<code>json</code>,<code>png</code>这样。例如:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.post('/user')
.type('application/json')

request.post('/user')
.type('json')

request.post('/user')
.type('png')
</code></pre>
</div>
<h2>9 序列化请求体</h2>
<p>SuperAgent会自动序列化JSON和表单数据,你也可以为其他类型设置自动序列化:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request<span class="token punctuation">.serialize<span class="token punctuation">[<span class="token string">'application/xml'<span class="token punctuation">] <span class="token operator">= <span class="token keyword">function <span class="token punctuation">(<span class="token parameter">obj<span class="token punctuation">) <span class="token punctuation">{
    <span class="token keyword">return <span class="token string">'string generated from obj'<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">;

<span class="token comment">// going forward, all requests with a Content-type of
<span class="token comment">// 'application/xml' will be automatically serialized
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>如果你希望以自定义格式发送数据,可以通过<code>.serialize()</code>方法为每个请求设置相应的序列化方法,以替换内置序列化方法:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request
    <span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
    <span class="token punctuation">.<span class="token function">send<span class="token punctuation">(<span class="token punctuation">{foo<span class="token punctuation">: <span class="token string">'bar'<span class="token punctuation">}<span class="token punctuation">)
    <span class="token punctuation">.<span class="token function">serialize<span class="token punctuation">(<span class="token parameter">obj <span class="token operator">=&gt; <span class="token punctuation">{
      <span class="token keyword">return <span class="token string">'string generated from obj'<span class="token punctuation">;
    <span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>10 重发请求</h2>
<p>当给定<code>retry()</code>方法时,SuperAgent将自动重试请求,如果它们以短暂的方式失败或者可能由于因特网连接不正常而失败。</p>
<p>这个方法有两个可选参数:重试次数(默认值3)和回调函数。它在每次重发之前调用回调<code>(error, res)</code>。回调可以返回<code>true/false</code>,以决定是否要重发请求。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'https://example.com/search'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">retry<span class="token punctuation">(<span class="token number">2<span class="token punctuation">) <span class="token comment">// or:
<span class="token punctuation">.<span class="token function">retry<span class="token punctuation">(<span class="token number">2<span class="token punctuation">, callback<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(finished<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>需要注意的是:应该只对HTTP等幂请求使用<code>retry()</code>方法(即,到达服务器的多个请求不会导致不希望的副作用,如重复购买,否则会产生多个订单)。</p>
<h2>11 设置Accept</h2>
<p>与<code>type()</code>方法一样,这里可以调用<code>accept()</code>方法来设置Accept接受类型,这个值将会被<code>request.types</code>所引用,支持传递一个规范的<code>MIME</code>名称,包括<code>type/subtype</code>,或者一个简单的后缀:<code>xml</code>,<code>json,``png</code>等。例如:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">accept<span class="token punctuation">(<span class="token string">'application/json'<span class="token punctuation">)

request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">accept<span class="token punctuation">(<span class="token string">'json'<span class="token punctuation">)

request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">accept<span class="token punctuation">(<span class="token string">'png'<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p><strong>Facebook和接收JSON</strong>:如果你是在调用<strong>Facebook</strong>的API,确保请求头中<code>Accept: application/json</code> 。否则,<strong>Facebook</strong> 将返回<code>Content-Type: text/javascript; charset=UTF-8</code>响应, <strong>SuperAgent</strong>将不会解析这个响应,读取响应体会得到<code>undefined</code>。你需要在请求对象<code>request</code>加上<code>request.accept('json')</code>或者<code>request.header('Accept', 'application/json')</code>代码。</p>
<h2>12 查询字符串</h2>
<p>调用.query()方法可以自动生成查询字符串,比如向URL为<code>?format=json&amp;dest=/login</code>发送一个post请求:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request
.post('/')
.query({ format: 'json' })
.query({ dest: '/login' })
.send({ post: 'data', here: 'wahoo' })
.then(callback);
</code></pre>
</div>
<p>默认情况下,查询字符串的拼装是没有特定的顺序。调用<code>sortQuery()</code>方法将默认按照ASCII码顺序进行,你也可以传递一个比较函数来指定排序规则,比较函数需要传递两个参数(在回调过程中会自动传递进两个参数,这两个参数就是用于比较的查询字符串),返回值是正整数、负整数或者0。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart"><span class="token comment">// 选择默认排序
request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'name=Nick'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'search=Manny'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">sortQuery<span class="token punctuation">(<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)

<span class="token comment">// 客制化的排序函数
request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/user'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'name=Nick'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">query<span class="token punctuation">(<span class="token string">'search=Manny'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">sortQuery<span class="token punctuation">(<span class="token punctuation">(a<span class="token punctuation">, b<span class="token punctuation">) <span class="token operator">=<span class="token operator">&gt; a<span class="token punctuation">.length <span class="token operator">- b<span class="token punctuation">.length<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>上述客制化的排序函数中,<code>a</code>和<code>b</code>实际上就是<code>sortQuery()</code>回调过程中传递进去的两个查询字符串,按照查询字符串长度来排序的,长度大的排在前面。</p>
<h2>13 TLS选项</h2>
<p>在Node.js中使用SuperAgent,支持对HTTPS请求的下列配置:</p>
<ul>
<li><code>ca()</code>:将CA证书设置为信任</li>
<li><code>cert()</code>:设置客户端证书链</li>
<li><code>key()</code>: 设置客户端私钥</li>
<li><code>pfx()</code>: 设置客户端PFX或PKCS12编码的私钥和证书链</li>
</ul>
<p>更多信息可以查看:https.request 官方文档.</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">var key <span class="token operator">= fs<span class="token punctuation">.<span class="token function">readFileSync<span class="token punctuation">(<span class="token string">'key.pem'<span class="token punctuation">)<span class="token punctuation">,
    cert <span class="token operator">= fs<span class="token punctuation">.<span class="token function">readFileSync<span class="token punctuation">(<span class="token string">'cert.pem'<span class="token punctuation">)<span class="token punctuation">;

request
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/client-auth'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">key<span class="token punctuation">(key<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">cert<span class="token punctuation">(cert<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token keyword">var ca <span class="token operator">= fs<span class="token punctuation">.<span class="token function">readFileSync<span class="token punctuation">(<span class="token string">'ca.cert.pem'<span class="token punctuation">)<span class="token punctuation">;

request
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'https://localhost/private-ca-server'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">ca<span class="token punctuation">(ca<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">res <span class="token operator">=&gt; <span class="token punctuation">{<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>14 解析响应体</h2>
<p><strong>SuperAgent</strong> 可以解析常用的响应体,目前支持<code>application/x-www-form-urlencoded</code>,<code>application/json</code>, 和<code>multipart/form-data</code>格式。如下代码,你也可以对其它类型的响应体设置相应的解析方法:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token comment">// 浏览器端使用SuperAgent
request<span class="token punctuation">.parse<span class="token punctuation">[<span class="token string">'application/xml'<span class="token punctuation">] <span class="token operator">= <span class="token keyword">function <span class="token punctuation">(<span class="token parameter">str<span class="token punctuation">) <span class="token punctuation">{
    <span class="token keyword">return <span class="token punctuation">{<span class="token string">'object'<span class="token punctuation">: <span class="token string">'parsed from str'<span class="token punctuation">}<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">;

<span class="token comment">// Node中使用SuperAgent
request<span class="token punctuation">.parse<span class="token punctuation">[<span class="token string">'application/xml'<span class="token punctuation">] <span class="token operator">= <span class="token keyword">function <span class="token punctuation">(<span class="token parameter">res<span class="token punctuation">, cb<span class="token punctuation">) <span class="token punctuation">{

    <span class="token comment">// 解析响应内容,设置响应体代码

    <span class="token function">cb<span class="token punctuation">(<span class="token keyword">null<span class="token punctuation">, res<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">;

<span class="token comment">// 自动解析响应体

</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>通过调用<code>buffer(true)</code>和<code>parse(fn)</code>的配合,你可以设置一个定制的解析器(定制的解析器优先于内置解析器)。 如果没有启用响应缓冲(<code>buffer(false)</code>),那么响应事件的触发将不会等待主体解析器完成,因此响应体将不可用。</p>
<h4>14.1 JSON/Urlencoded</h4>
<p><code>response.body</code>是解析后的内容对象,比如对于一个请求响应<code>'{"user":{"name":"tobi"}}'</code>字符串,<code>response.body.user.name</code>会返回<code>"tobi"</code>。同样的,与<code>x-www-form-urlencoded</code>格式的<code>"user=tobi"</code>解析后值也是一样,只支持嵌套的一个层次,如果需要更复杂的数据,请使用JSON格式。</p>
<p>数组会以重复键名的方式进行发送,<code>send({color: ['red','blue']})</code>会发送<code>"color=red&amp;color=blue"</code>。如果你希望数组键的名称包含<code>"[]"</code>,则需要自己添加,<strong>SuperAgent</strong>是不会自动添加。</p>
<h4>14.2 Multipart</h4>
<p>Node客户端通过Formidable模块来支持<code>multipart/form-data</code>类型,当解析一个<code>multipart</code>响应时,<code>response.files</code>属性就可以用。假设一个请求响应得到下面的数据:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart"><span class="token operator">--whoop
Content<span class="token operator">-Disposition<span class="token punctuation">: attachment<span class="token punctuation">; name<span class="token operator">=<span class="token string">"image"<span class="token punctuation">; filename<span class="token operator">=<span class="token string">"tobi.png"
Content<span class="token operator">-Type<span class="token punctuation">: image<span class="token operator">/png

<span class="token punctuation">.<span class="token punctuation">.<span class="token punctuation">. data here <span class="token punctuation">.<span class="token punctuation">.<span class="token punctuation">.
<span class="token operator">--whoop
Content<span class="token operator">-Disposition<span class="token punctuation">: form<span class="token operator">-data<span class="token punctuation">; name<span class="token operator">=<span class="token string">"name"
Content<span class="token operator">-Type<span class="token punctuation">: text<span class="token operator">/plain

Tobi
<span class="token operator">--whoop<span class="token operator">--
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>你可以获取到<code>res.body.name</code>名为<code>’Tobi’</code>,<code>res.files.image</code>为一个<code>file</code>对象,包括一个磁盘文件路径、文件名称,还有其它的文件属性。</p>
<h4>14.3 Binary</h4>
<p>在浏览器中可以使用<code>responseType('blob')</code>来请求处理二进制格式的响应体。在Node.js中运行此API是不必要的。此方法的支持参数值为:</p>
<ul>
<li><code>'blob'</code>:会被传递为<code>XmlHTTPRequest</code>的<code>responseType</code>属性。</li>
<li><code>'arraybuffer'</code>:会被传递为<code>XmlHTTPRequest</code>的<code>responseType</code>属性。</li>
</ul>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">req<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/binary.data'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">responseType<span class="token punctuation">(<span class="token string">'blob'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(res <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
    <span class="token comment">// res.body will be a browser native Blob type here
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>更多的信息可以查看:xhr.responseType 文档.</p>
<h2>15 响应对象属性</h2>
<p><strong>SuperAgent</strong>请求得到响应后,响应对象的属性主要有:</p>
<ul>
<li>
<p><code>text</code>:未解析前的响应内容,字符串类型。一般只在<code>mime</code>类型能够匹配<code>"text/"</code>,<code>"json"</code>,<code>"x-www-form-urlencoding"</code>的情况下,这个属性才会有效,默认为nodejs客户端提供;</p>
</li>
<li>
<p><code>body</code>:响应数据解析后的对象,对象类型。</p>
</li>
<li>
<p><code>header</code>:解析之后的响应头数据,数组类型。</p>
</li>
<li>
<p><code>type</code>:响应报文的<code>Content-Type</code>值,字符串类型。</p>
</li>
<li>
<p><code>charset</code>:响应的字符集,字符串类型。</p>
</li>
<li>
<p><code>status</code>:响应状态标识。</p>
</li>
<li>
<p><code>statusCode</code>:响应的状态码,数整数类型。如:200、302、404、500等。</p>
</li>
</ul>
<h4>15.1 text</h4>
<p><code>response.text</code>包含未解析前的响应内容,一般只在<code>mime</code>类型能够匹配<code>"text/"</code>,<code>"json"</code>,<code>"x-www-form-urlencoding"</code>的情况下,这个属性才会有效,默认为nodejs客户端提供,这是出于节省内存的考虑。因为缓冲大数据量的文本(如multipart文件或图像)的效率非常低。要强制缓冲,请参阅<strong>“响应缓冲”</strong>部分。</p>
<h4>15.2 body</h4>
<p>与<strong>SuperAgent</strong>请求数据自动序列化一样,响应数据也会自动的解析,当为一个<code>Content-Type</code>定义一个解析器后,就能自动解析,默认解析包含<code>application/json</code>和<code>application/x-www-form-urlencoded</code>,可以通过<code>response.body</code>来访问解析对象.</p>
<h4>15.3 header fields</h4>
<p>response.header包含解析之后的响应头数据,字段值都是Node处理成小写字母形式,如<code>response.header['content-length']</code>。</p>
<h4>15.4 Content-Type</h4>
<p><code>Content-Type</code>响应头字段是一个特列,服务器提供<code>response.type</code>来访问它,默认<code>response.charset</code>是空的(如果有的话,则为指定类型),例如<code>Content-Type</code>值为<code>"text/html; charset=utf8"</code>,则<code>response.type</code>为<code>text/html</code>,<code>response.charset</code>为<code>"utf8"</code>。</p>
<h4>15.5 status</h4>
<p>响应状态标识可以用来判断请求是否成功,除此之外,可以用<strong>SuperAgent</strong>来构建理想的<strong>RESTful</strong>服务器,这些标识目前定义为:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-go"><code class="language-go"><span class="token keyword">var <span class="token keyword">type <span class="token operator">= status <span class="token operator">/ <span class="token number">100 <span class="token operator">| <span class="token number">0<span class="token punctuation">;

<span class="token comment">// status / class
res<span class="token punctuation">.status <span class="token operator">= status<span class="token punctuation">;
res<span class="token punctuation">.statusType <span class="token operator">= <span class="token keyword">type<span class="token punctuation">;

<span class="token comment">// basics
res<span class="token punctuation">.info <span class="token operator">= <span class="token number">1 <span class="token operator">== <span class="token keyword">type<span class="token punctuation">;
res<span class="token punctuation">.ok <span class="token operator">= <span class="token number">2 <span class="token operator">== <span class="token keyword">type<span class="token punctuation">;
res<span class="token punctuation">.clientError <span class="token operator">= <span class="token number">4 <span class="token operator">== <span class="token keyword">type<span class="token punctuation">;
res<span class="token punctuation">.serverError <span class="token operator">= <span class="token number">5 <span class="token operator">== <span class="token keyword">type<span class="token punctuation">;
res<span class="token punctuation">.<span class="token builtin">error <span class="token operator">= <span class="token number">4 <span class="token operator">== <span class="token keyword">type <span class="token operator">|| <span class="token number">5 <span class="token operator">== <span class="token keyword">type<span class="token punctuation">;

<span class="token comment">// sugar
res<span class="token punctuation">.accepted <span class="token operator">= <span class="token number">202 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.noContent <span class="token operator">= <span class="token number">204 <span class="token operator">== status <span class="token operator">|| <span class="token number">1223 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.badRequest <span class="token operator">= <span class="token number">400 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.unauthorized <span class="token operator">= <span class="token number">401 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.notAcceptable <span class="token operator">= <span class="token number">406 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.notFound <span class="token operator">= <span class="token number">404 <span class="token operator">== status<span class="token punctuation">;
res<span class="token punctuation">.forbidden <span class="token operator">= <span class="token number">403 <span class="token operator">== status<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>16.中止请求</h2>
<p>可以通过<code>req.abort()</code>来中止请求。</p>
<h2>17.请求超时</h2>
<p>有时网络和服务器会“卡住”,并且在接受请求后从不响应。设置超时以避免请求永远等待。</p>
<ul>
<li>
<p><code>req.timeout({deadline:ms})</code> 或 <code>req.timeout(ms)</code>: ms是大于0的毫秒数。为整个请求设置一个截止时间(包括所有上传、重定向、服务器处理时间)完成。如果在那个时间内没有得到完整的响应,请求将被中止。</p>
</li>
<li>
<p><code>req.timeout({response:ms})</code>:设置等待第一个字节从服务器到达的最大时间,但不限制整个下载可以消耗多长时间。响应超时应该比服务器响应的时间长至少几秒钟,因为它还包括进行DNS查找、TCP/IP和TLS连接的时间,以及上传请求数据的时间。</p>
</li>
</ul>
<p>你应该同时使用<code>deadline</code>和<code>response</code>超时。通过这种方式,你可以通过较短的<code>response</code>超时来快速检测无响应网络,并且使用较长的<code>deadline</code>来在缓慢但可靠的网络上提供一个合适的时间。注意,这两个计时器都限制了上传文件的上传时间。如果上传文件,则使用长时间超时。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-tsx"><code class="language-tsx">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/big-file?network=slow'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">timeout<span class="token punctuation">(<span class="token punctuation">{
    response<span class="token punctuation">: <span class="token number">5000<span class="token punctuation">,<span class="token comment">// Wait 5 seconds for the server to start sending,
    deadline<span class="token punctuation">: <span class="token number">60000<span class="token punctuation">, <span class="token comment">// but allow 1 minute for the file to finish loading.
<span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">res <span class="token operator">=&gt; <span class="token punctuation">{
      <span class="token comment">/* responded in time */
    <span class="token punctuation">}<span class="token punctuation">, <span class="token parameter">err <span class="token operator">=&gt; <span class="token punctuation">{
      <span class="token keyword">if <span class="token punctuation">(err<span class="token punctuation">.timeout<span class="token punctuation">) <span class="token punctuation">{ <span class="token comment">/* timed out! */ <span class="token punctuation">} <span class="token keyword">else <span class="token punctuation">{ <span class="token comment">/* other error */ <span class="token punctuation">}
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>超时错误会提供一个<code>timeout</code>属性。</p>
<h2>18.认证</h2>
<p>Node和浏览器中都可以通过<code>auth()</code>方法来完成认证。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'http://local'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">auth<span class="token punctuation">(<span class="token string">'tobi'<span class="token punctuation">, <span class="token string">'learnboost'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>nodejs客户端也可以通过传递一个像下面这样的URL:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'http://tobi:learnboost@local'<span class="token punctuation">)<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>默认在浏览器中只使用基本的认证方式,你也可以添加<code>{type:'auto'}</code>,以启用浏览器中内置的所有方法(摘要、NTLM等):</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request.auth('digest', 'secret', {type:'auto'})
</code></pre>
</div>
<h2>19.跟随重定向</h2>
<p>默认是向上跟随5个重定向,可以通过调用.res.redirects(n)来设置个数:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/some.png'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">redirects<span class="token punctuation">(<span class="token number">2<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>20.全局状态代理</h2>
<h4>20.1 保存cookies</h4>
<p>在Node SuperAgent中,默认情况下不保存cookie,但是可以使用.agent()方法创建一个含有cookie的SuperAgent副本。每个副本都有一个单独的cookie数据。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart"><span class="token keyword">const agent <span class="token operator">= request<span class="token punctuation">.<span class="token function">agent<span class="token punctuation">(<span class="token punctuation">)<span class="token punctuation">;
agent
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/login'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token punctuation">(<span class="token punctuation">) <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
    <span class="token keyword">return agent<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/cookied-page'<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>在浏览器中,cookie由浏览器自动管理,因此<code>.agent()</code>不会格式化处理cookies。</p>
<h4>20.2 多请求的默认选项</h4>
<p>使用<code>agent</code>进行的多个请求中,<code>agent</code>调用的常规方法也将默认用于<code>agent</code>的后续所有的请求中。这些常规方法包括:<code>use</code>, <code>on</code>, <code>once</code>, <code>set</code>, <code>query</code>, <code>type</code>, <code>accept</code>, <code>auth</code>, <code>withCredentials</code>, <code>sortQuery</code>, <code>retry</code>, <code>ok</code>, <code>redirects</code>, <code>timeout</code>, <code>buffer</code>, <code>serialize</code>, <code>parse</code>, <code>ca</code>, <code>key</code>, <code>pfx</code>, <code>cert</code>。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">const agent <span class="token operator">= request<span class="token punctuation">.<span class="token function">agent<span class="token punctuation">(<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">use<span class="token punctuation">(plugin<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">auth<span class="token punctuation">(shared<span class="token punctuation">)<span class="token punctuation">;

<span class="token keyword">await agent<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/with-plugin-and-auth'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">await agent<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/also-with-plugin-and-auth'<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>21.管道数据</h2>
<p>在nodejs客户端中,可以使用一个请求流来传输数据。需要注意的是:用<code>pipe()</code>取代了<code>end()</code>和<code>then()</code>方法。</p>
<p>下面是将文件内容作为请求进行管道传输例子:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx"><span class="token keyword">const request <span class="token operator">= <span class="token function">require<span class="token punctuation">(<span class="token string">'superagent'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const fs <span class="token operator">= <span class="token function">require<span class="token punctuation">(<span class="token string">'fs'<span class="token punctuation">)<span class="token punctuation">;

<span class="token keyword">const stream <span class="token operator">= fs<span class="token punctuation">.<span class="token function">createReadStream<span class="token punctuation">(<span class="token string">'path/to/my.json'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const req <span class="token operator">= request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/somewhere'<span class="token punctuation">)<span class="token punctuation">;
req<span class="token punctuation">.<span class="token function">type<span class="token punctuation">(<span class="token string">'json'<span class="token punctuation">)<span class="token punctuation">;
stream<span class="token punctuation">.<span class="token function">pipe<span class="token punctuation">(req<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>注意,在管道传输到请求时,superagent使用分块传输编码发送管道数据,这不是所有服务器(例如Python WSGI服务器)都支持的。</p>
<p>下面是输送一个响应流到文件的管道传输例子:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">const stream <span class="token operator">= fs<span class="token punctuation">.<span class="token function">createWriteStream<span class="token punctuation">(<span class="token string">'path/to/my.json'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const req <span class="token operator">= request<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/some.json'<span class="token punctuation">)<span class="token punctuation">;
req<span class="token punctuation">.<span class="token function">pipe<span class="token punctuation">(stream<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>不能将管道、回调或<code>promise</code>混合在一起使用,不能尝试对<code>end()</code>或<code>response</code>对象进行管道操作(<code>pipe()</code>),如下所示:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart"><span class="token comment">// 不能做下面的操作
<span class="token keyword">const stream <span class="token operator">= <span class="token function">getAWritableStream<span class="token punctuation">(<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const req <span class="token operator">= request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/some.json'<span class="token punctuation">)
<span class="token comment">// BAD: this pipes garbage to the stream and fails in unexpected ways
<span class="token punctuation">.<span class="token function">end<span class="token punctuation">(<span class="token punctuation">(err<span class="token punctuation">, this_does_not_work<span class="token punctuation">) <span class="token operator">=<span class="token operator">&gt; this_does_not_work<span class="token punctuation">.<span class="token function">pipe<span class="token punctuation">(stream<span class="token punctuation">)<span class="token punctuation">)
<span class="token keyword">const req <span class="token operator">= request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/some.json'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">end<span class="token punctuation">(<span class="token punctuation">)
<span class="token comment">// BAD: this is also unsupported, .pipe calls .end for you.
<span class="token punctuation">.<span class="token function">pipe<span class="token punctuation">(nope_its_too_late<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>22.Multipart/form-data请求</h2>
<p>superagen提供了<code>attach()</code> 和 <code>field()</code>方法用于构建multipart/form-data请求。</p>
<p>当你使用了<code>field()</code>或者<code>attach()</code>,你就不能使用 <code>send()</code>方法,你也不能设置 Content-Type (superagen会自动设置纠正后的<code>type</code>)。</p>
<h4>22.1 附件</h4>
<p>可以使用<code>attach(name, , )</code>进行文件发送。你可以通过多次调用<code>attach()</code>附加多个文件。<code>attach()</code>的参数说明如下:</p>
<ul>
<li><code>name</code>:文件名</li>
<li><code>file</code>:文件路径字符串,或Blob/Buffer对象。</li>
<li><code>options</code> :(可选)字符串或自定义文件名或<code>{filename: string}</code>对象。在Node中也支持<code>{contentType: 'mime/type'}</code>。在浏览器中创建一个具有适当类型的<code>Blob</code>。</li>
</ul>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash">request
.post('/upload')
.attach('image1', 'path/to/felix.jpeg')
.attach('image2', imageBuffer, 'luna.jpeg')
.field('caption', 'My cats')
.then(callback);
</code></pre>
</div>
<h4>22.2 字段值</h4>
<p>与HTML中表单的字段类似,你可以调用<code>field(name,value)</code>方法来设置字段,假设你想上传一个图片的并附带自己的名称和邮箱,那么你可以像下面这样:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-bash"><code class="language-bash"> request
   .post('/upload')
   .field('user', 'Tobi')
   .field('user', 'tobi@learnboost.com')
   .field('friends[]', ['loki', 'jane'])
   .attach('image', 'path/to/tobi.png')
   .then(callback);
</code></pre>
</div>
<h2>23.压缩</h2>
<p>NodeJS客户端本身就提供压缩响应内容,所以你不需要做任何其它处理。</p>
<h2>24.响应缓冲</h2>
<p>为了强制缓冲<code>response.text</code>这样未解析前的响应内容(一般只在mime类型能够匹配"text/","json","x-www-form-urlencoding"的情况下才进行缓冲),可以调用<code>buffer()</code>方法,想取消默认的文本缓冲响应像<code>text/plain</code>, <code>text/html</code>这样的,可以调用<code>buffer(false)</code>方法。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token comment">// 强制缓冲
request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/userinfo'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">buffer<span class="token punctuation">(<span class="token keyword">true<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)

<span class="token comment">// 取消缓冲
request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'/userinfo'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">buffer<span class="token punctuation">(<span class="token keyword">false<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(callback<span class="token punctuation">)

</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>当缓冲<code>response.buffered</code>标识有效了,那么就可以在一个回调函数里处理缓冲和未缓冲的响应.</p>
<h2>25.跨域资源共享(CORS)</h2>
<p>出于安全原因,浏览器将阻止跨源请求,除非服务器使用CORS头进行选择。浏览器还将做出额外的选项请求,以检查服务器允许的HTTP头和方法。更多信息可参阅:CORS.</p>
<p><code>withCredentials()</code>方法可以激活发送原始<code>cookie</code>的能力,不过只有在<code>Access-Control-Allow-Origin</code>不是一个通配符<code>(*)</code>,并且<code>Access-Control-Allow-Credentials</code>为<code>’true’</code>的情况下才行。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'https://api.example.com:4001/'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">withCredentials<span class="token punctuation">(<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(res <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{
    <span class="token keyword">assert<span class="token punctuation">.<span class="token function">equal<span class="token punctuation">(<span class="token number">200<span class="token punctuation">, res<span class="token punctuation">.status<span class="token punctuation">)<span class="token punctuation">;
    <span class="token keyword">assert<span class="token punctuation">.<span class="token function">equal<span class="token punctuation">(<span class="token string">'tobi'<span class="token punctuation">, res<span class="token punctuation">.text<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>26.错误处理</h2>
<p>回调函数总是会传递两个参数:<code>error</code> 错误和<code>response</code> 响应。如果没有发生错误,第一个参数将为<code>null</code>。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/upload'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">attach<span class="token punctuation">(<span class="token string">'image'<span class="token punctuation">, <span class="token string">'path/to/tobi.png'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">response <span class="token operator">=&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>你可以加入监听错误的代码,错误产生之后会执行监听代码。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-dart"><code class="language-dart">request
<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token string">'/upload'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">attach<span class="token punctuation">(<span class="token string">'image'<span class="token punctuation">, <span class="token string">'path/to/tobi.png'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">on<span class="token punctuation">(<span class="token string">'error'<span class="token punctuation">, handle<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(response <span class="token operator">=<span class="token operator">&gt; <span class="token punctuation">{

<span class="token punctuation">}<span class="token punctuation">)<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p><strong>注意:</strong><br>
superagent默认情况下,对响应4xx和5xx的认为不是错误,例如当响应返回一个500或者403的时候,这些状态信息可以通过<code>response.error</code>,<code>response.status</code>和其它的响应属性来查看。</p>
<p>不产生响应的网络故障、超时和其他错误将不包含<code>response.error</code>,<code>response.status</code>属性。</p>
<p>如果希望处理404个或其他HTTP错误响应,可以查询<code>error.status</code>属性。当发生HTTP错误(4xx或5xx响应)时,<code>response.error</code>属性是<code>error</code>对象,这可以用来作以下检查:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">if <span class="token punctuation">(error <span class="token operator">&amp;&amp; error<span class="token punctuation">.status <span class="token operator">==<span class="token operator">= <span class="token number">404<span class="token punctuation">) <span class="token punctuation">{
<span class="token function">alert<span class="token punctuation">(<span class="token string">'oh no ' <span class="token operator">+ response<span class="token punctuation">.body<span class="token punctuation">.message<span class="token punctuation">)<span class="token punctuation">;
<span class="token punctuation">}
<span class="token keyword">else <span class="token keyword">if <span class="token punctuation">(error<span class="token punctuation">) <span class="token punctuation">{
<span class="token comment">// all other error types we handle generically
<span class="token punctuation">}
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>或者,可以使用<code>ok(callback)</code>方法来判断响应是否是错误。对<code>ok()</code>的回调得到响应,如果响应成功,则返回true。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request<span class="token punctuation">.<span class="token function">get<span class="token punctuation">(<span class="token string">'/404'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">ok<span class="token punctuation">(<span class="token parameter">res <span class="token operator">=&gt; res<span class="token punctuation">.status <span class="token operator">&lt; <span class="token number">500<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token parameter">response <span class="token operator">=&gt; <span class="token punctuation">{
    <span class="token comment">// reads 404 page as a successful response
<span class="token punctuation">}<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<h2>27.进度跟踪</h2>
<p>superagent在大型文件的上传和下载过程中触发<code>progress</code>事件。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp">request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(url<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">attach<span class="token punctuation">(<span class="token string">'field_name'<span class="token punctuation">, file<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">on<span class="token punctuation">(<span class="token string">'progress'<span class="token punctuation">, <span class="token keyword">event <span class="token operator">=&gt; <span class="token punctuation">{
    <span class="token comment">/* 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
    } */
<span class="token punctuation">}<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">then<span class="token punctuation">(<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>event属性包括:</p>
<ul>
<li><code>direction</code>: <code>upload</code> 或 <code>download</code></li>
<li><code>percent</code>:<code>0</code> 到 <code>100</code> ,文件大小未知的话为无效</li>
<li><code>total</code>:文件总大小,可能为无效</li>
<li><code>loaded</code>: 已经下载或上传的字节数</li>
</ul>
<h2>28.Promise和Generator支持</h2>
<p>SuperAgent的请求是一个“thenable”对象,它与JavaScript承诺和异步/等待语法兼容。</p>
<p>如果你正在使用<code>promises</code>,那么就不要再调用<code>end()</code>或<code>pipe()</code>方法。任何使用<code>then()</code>或者<code>await</code>操作都会禁用所有其他使用请求的方式。</p>
<p>像CO或类似KOA这样的Web框架,可以在superagent使用<code>yield</code>:</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-csharp"><code class="language-csharp"><span class="token keyword">const req <span class="token operator">= request
<span class="token punctuation">.<span class="token keyword">get<span class="token punctuation">(<span class="token string">'http://local'<span class="token punctuation">)
<span class="token punctuation">.<span class="token function">auth<span class="token punctuation">(<span class="token string">'tobi'<span class="token punctuation">, <span class="token string">'learnboost'<span class="token punctuation">)<span class="token punctuation">;
<span class="token keyword">const res <span class="token operator">= <span class="token keyword">yield req<span class="token punctuation">;
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
<p>请注意,superagent期望全局<code>promises</code>对象存在。在Internet Explorer或Node.js 0.10中需要使用<code>polyfill</code>组件。</p>
<h2>29.浏览器和Node版本</h2>
<p>SuperAgent有两个实现:一个是用于web浏览器(使用XHR)的版本,另一个是用于Node.JS (使用核心的http模块)版本。</p>
<h2>30.3XX处理</h2>
<p>HTTP 3XX是重定向报文,superagent默认会自动跟踪下去,我们也不能使用<code>redirect(0)</code>的方法来禁止重定向,因此需要使用原生的<code>http</code>来处理。</p>
<div class="_2Uzcx_"><button class="VJbwyy" type="button"></button>
<pre class="line-numberslanguage-jsx"><code class="language-jsx">request<span class="token punctuation">.<span class="token function">post<span class="token punctuation">(<span class="token punctuation">{
url<span class="token punctuation">: <span class="token string">'/login'<span class="token punctuation">,
<span class="token punctuation">}<span class="token punctuation">, <span class="token keyword">function <span class="token punctuation">(<span class="token parameter">err<span class="token punctuation">, res<span class="token punctuation">, body<span class="token punctuation">) <span class="token punctuation">{
<span class="token keyword">if <span class="token punctuation">(<span class="token operator">!err <span class="token operator">&amp;&amp; <span class="token punctuation">(res<span class="token punctuation">.statusCode <span class="token operator">== <span class="token number">301 <span class="token operator">|| res<span class="token punctuation">.statusCode <span class="token operator">== <span class="token number">302<span class="token punctuation">)<span class="token punctuation">) <span class="token punctuation">{
    <span class="token comment">// 登录成功后服务端返回重定位报文
    cookie <span class="token operator">+= <span class="token string">';' <span class="token operator">+ res<span class="token punctuation">.headers<span class="token punctuation">[<span class="token string">'set-cookie'<span class="token punctuation">]
    res1<span class="token punctuation">.<span class="token function">redirect<span class="token punctuation">(<span class="token string">'listall'<span class="token punctuation">)
<span class="token punctuation">} <span class="token keyword">else <span class="token keyword">if <span class="token punctuation">(res<span class="token punctuation">.statusCode <span class="token operator">== <span class="token number">200<span class="token punctuation">) <span class="token punctuation">{
    <span class="token comment">// 登录失败服务端会返回200
    <span class="token comment">// ...
<span class="token punctuation">} <span class="token keyword">else <span class="token punctuation">{
    <span class="token comment">// 其他错误信息处理
    console<span class="token punctuation">.<span class="token function">log<span class="token punctuation">(err<span class="token punctuation">)
<span class="token punctuation">}
<span class="token punctuation">}<span class="token punctuation">)
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
</div>
<p></audio></p><br><br>
来源:https://www.cnblogs.com/chris-oil/p/12602378.html
頁: [1]
查看完整版本: [转] SuperAgent使用文档