New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[翻译] SuperAgent 中文使用指南(v3.8.0) #13

Open
zhaoqize opened this Issue Jan 17, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@zhaoqize
Owner

zhaoqize commented Jan 17, 2018

版本: v3.8.0
SuperAgent 英文使用指南

SuperAgent

SuperAgent是轻量级渐进式ajax API,相比于现有的请求API,它更加灵活,可读,且学习成本低。 同样它也适用于Node.js!

 request
   .post('/api/pet')
   .send({ name: 'Manny', species: 'cat' })
   .set('X-API-Key', 'foobar')
   .set('Accept', 'application/json')
   .then(function(res) {
      alert('yay got ' + JSON.stringify(res.body));
   });

测试文档

以下 测试文档 是由Mocha's "doc" 记录生成的,直接反映了测试套件。 这提供了额外的文档来源。

基础请求

请求可以通过调用 request 对象的适当方法来启动,然后调用.then() (or .end() or await) 来发送请求,例如一个简单的GET请求:

 request
   .get('/search')
   .then(function(res) {
      // res.body, res.headers, res.status
   })
   .catch(function(err) {
      // err.message, err.response
   });

HTTP 方法也可以使用字符串:

request('GET', '/search').then(success, failure);

旧的回调依旧可以使用。 将 .then() 替换成 .end()

request('GET', '/search').end(function(err, res){
  if (res.ok) {}
});

可以使用绝对URL。 在Web浏览器中,绝对URL只在服务器实现 CORS 的情况下才起作用。

 request
   .get('http://example.com/search')
   .then(function(res) {

   });

Node 客户端支持向 Unix域套接字 发送请求:

 // pattern: https?+unix://SOCKET_PATH/REQUEST_PATH
 //          Use `%2F` as `/` in SOCKET_PATH
 request
   .get('http+unix://%2Fabsolute%2Fpath%2Fto%2Funix.sock/search')
   .then(res => {

   });

DELETE , HEAD , PATCH , POST , 和 PUT 请求方法依旧可以使用, 只需要修改一下方法名即可:

request
  .head('/favicon.ico')
  .then(function(res) {

  });

DELETE 也可以被称为.del()与旧的IE兼容,其中delete是一个保留字。

HTTP 方法默认是 GET,所以下面的写法也是可以的:

 request('/search', function(err, res){

 });

设置 header 字段

设置标题字段很简单,用字段名和值调用 .set():

 request
   .get('/search')
   .set('API-Key', 'foobar')
   .set('Accept', 'application/json')
   .then(callback);

你也可以传递一个对象来在一次调用中设置几个字段:

 request
   .get('/search')
   .set({ 'API-Key': 'foobar', Accept: 'application/json' })
   .then(callback);

GET 请求

.query() 方法接受对象,当与 GET 方法一起使用时,将形成一个查询字符串。 以下将拼接成/ search?query = Manny&range = 1..5&order = desc这样的一个查询字符串。

 request
   .get('/search')
   .query({ query: 'Manny' })
   .query({ range: '1..5' })
   .query({ order: 'desc' })
   .then(function(res) {

   });

或者用一个对象包裹:

request
  .get('/search')
  .query({ query: 'Manny', range: '1..5', order: 'desc' })
  .then(function(res) {

  });

.query() 方法同样可以接收字符串的形式:

  request
    .get('/querystring')
    .query('search=Manny&range=1..5')
    .then(function(res) {

    });

或者如下这样:

  request
    .get('/querystring')
    .query('search=Manny')
    .query('range=1..5')
    .then(function(res) {

    });

HEAD 请求

对于 HEAD 请求你依旧可以使用 .query() 方法。下面的 .query() 参数将会拼接成 /users?email=joe@smith.com

  request
    .head('/users')
    .query({ email: 'joe@smith.com' })
    .then(function(res) {

    });

POST / PUT 请求

一个典型的JSON POST 请求可能看起来有点像下面这样,我们适当地设置 Content-Type 头字段,并“写”一些数据,在这种情况下,只是一个JSON字符串。

  request.post('/user')
    .set('Content-Type', 'application/json')
    .send('{"name":"tj","pet":"tobi"}')
    .then(callback)

JSON无疑是最常见的,这就是 默认的 ! 下面的例子等同于前面的例子

  request.post('/user')
    .send({ name: 'tj', pet: 'tobi' })
    .then(callback)

或调用多次 .send():

  request.post('/user')
    .send({ name: 'tj' })
    .send({ pet: 'tobi' })
    .then(callback)

默认情况下,发送字符串将把 Content-Type 设置为 application / x-www-form-urlencoded ,多个调用将与连接在一起,这里生成name = tj&pet = tobi

  request.post('/user')
    .send('name=tj')
    .send('pet=tobi')
    .then(callback);

SuperAgent 格式是可扩展的,但默认支持 "json" 和 "form"。 要以 application / x-www-form-urlencoded 方式发送数据,只需使用 "form" 调用 .type(),默认为“json”。 这个请求将 POST 的 body拼接成“名称= tj&pet = tobi"。

  request.post('/user')
    .type('form')
    .send({ name: 'tj' })
    .send({ pet: 'tobi' })
    .then(callback)

发送一个 FormData 格式的数据也是支持的。以下示例将 POST 标识为 id =“myForm” 的HTML表单的内容。

  request.post('/user')
    .send(new FormData(document.getElementById('myForm')))
    .then(callback)

设置 Content-Type

.set() 方法也是经常使用的:

 request.post('/user')
   .set('Content-Type', 'application/json')

作为一个简短方式, .type() 方法也是可用的,它接受规范化的 MIME 类型名称完整的类型/子类型,或简单的扩展名称,如“xml”,“json”,“png”:

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

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

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

序列化请求正文

SuperAgent会自动序列化JSON和表单。 如果要以自定义格式发送有效内容,则可以使用 .serialize()方法替换内置序列化。

重试请求

当给定 .retry() 方法时,SuperAgent 会自动重试请求,如果它们以短暂的失败或可能是由于Internet连接造成的。

此方法有两个可选参数:重试次数(默认值3)和回调。 它在每次重试之前调用 callback(err,res)。 回调可能返回 true /false 来控制请求是否被重试(但总是应用最大重试次数)。

 request
   .get('http://example.com/search')
   .retry(2) // or:
   .retry(2, callback)
   .then(finished);

仅对 幂等 的请求使用 .retry()

设置 Accept

类似于 .type() 方法,也可以通过简短的方法 .accept() 来设置 Accept 头。request.types 还允许您指定完整的规范化 MIME 类型名称为type/subtype,或者扩展后缀形式为“xml”,“json”,“png”:

 request.get('/user')
   .accept('application/json')

 request.get('/user')
   .accept('json')

 request.post('/user')
   .accept('png')

Facebook 和 Accept JSON

如果你正在调用 Facebook 的API,请确保在您的请求中发送 "Accept:application/json" 头。 如果你不这样做,Facebook 会用Content-Type:text / javascript; charset = UTF-8,SuperAgent 将不会解析,因此 res.body 将是未定义的。 你可以用 req.accept('json')req.header('Accept','application / json') 来做到这一点。 有关详细信息,请参见 issues1078

查询字符串

req.query(obj) 是一个可以用来建立一个查询字符串的方法。 例如,在 POST 上填充 ?format = json&dest = / login

request
  .post('/')
  .query({ format: 'json' })
  .query({ dest: '/login' })
  .send({ post: 'data', here: 'wahoo' })
  .then(callback);

默认情况下,查询字符串不会以任何特定的顺序组装的。 asciibetically-sorted 排序的查询字符串可以用req.sortQuery() 来启用。 你也可以用 req.sortQuery(myComparisonFn) 提供一个自定义的排序比较函数。 比较函数应该带2个参数并返回一个负/零/正整数。

 // default order
 request.get('/user')
   .query('name=Nick')
   .query('search=Manny')
   .sortQuery()
   .then(callback)

 // customized sort function
 request.get('/user')
   .query('name=Nick')
   .query('search=Manny')
   .sortQuery(function(a, b){
     return a.length - b.length;
   })
   .then(callback)

TLS 选项

在 Node.js 中,SuperAgent 支持配置 HTTPS 请求的方法:

  • .ca(): 将CA证书设置为信任
  • .cert(): 设置客户端证书链
  • .key(): 设置客户端私钥
  • .pfx(): 设置客户端PFX或PKCS12编码的私钥和证书链

更多信息,请看 Node.js https.request docs.

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 => {});

解析响应主体

SuperAgent 将为你解析已知的响应主体数据,目前支持 application / x-www-form-urlencodedapplication / jsonmultipart / form-data

您可以使用 .buffer(true).parse(fn) 方法设置自定义解析器(优先于内置解析器)。 如果没有启用响应缓冲 (.buffer(false)),那么 response 事件将不会等待 body 解析完成,所以 response.body 将不可用。

JSON / Urlencoded

例如,如果请求用JSON字符串 “{”user“:{”name“:”tobi“}}” 响应,那么 res.body.user.name 就是解析对象就是“tobi”。同样,“user [name] = tobi”的x-www-form-urlencoded值也会产生相同的结果。 只支持一个嵌套级别。 如果您需要更复杂的数据,请发送JSON。

通过重复key发送数组。 .send({color:['red','blue']}) 发送 color = red&color = blue。 如果你想让数组 key 在它们的名字中包含[],你必须自己添加它,因为SuperAgent不会自动添加它。

Multipart

Node客户端通过 Formidable 模块支持 multipart / form-data 。 当解析多部分响应时,对象 res.files 也可以使用。 假设例如一个请求用下面的多部分主体响应:

--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”对象。

二进制

在浏览器中,你可以使用 .responseType('blob') 来请求处理二进制响应主体。 在 node.js 中运行时,此API不是必要的。 这个方法支持的参数值是

  • blob 传递给 XmlHTTPRequest responseType 属性
  • arraybuffer' 传递给 XmlHTTPRequest responseType` 属性
req.get('/binary.data')
  .responseType('blob')
  .end(function (error, res) {
    // res.body will be a browser native Blob type here
  });

更多内容请看 Mozilla Developer Network xhr.responseType docs

响应属性

响应对象设置了许多有用的标志和属性,包括响应文本,解析的响应主体,标题字段,状态标志等等。

响应文本

res.text 属性包含未解析的响应正文字符串。 此属性始终为客户端API提供,并且仅当默认情况下mime类型与节点默认匹配“text / ”,“ / json”或“x-www-form-urlencoded”时。 其原因是为了节省内存,因为诸如多部分文件或图像的大型文本的缓存文本是非常低效的。 要强制缓存请参阅 “缓存响应” 部分。

响应体

与 SuperAgent 可以自动序列化请求数据一样,它也可以自动解析它。 当为 Content-Type 定义一个解析器时,它将被解析,默认包含 “application / json” 和 “application / x-www-form-urlencoded” 。 解析的对象然后可以通过 res.body 获得。

响应头字段

res.header包含一个解析的头部字段的对象,和节点一样压缩字段名称。 例如 res.header ['content-length']

响应类型

Content-Type 响应头是特殊的,提供 res.type,这是没有字符集(如果有的话)。 例如,“text / html; charset = utf8” 的 Content-Type 将提供“text / html”作为“res.type”,然后“res.charset”属性将包含“utf8”。

响应状态

响应状态标志有助于确定请求是否成功以及其他有用信息,从而使 SuperAgent 成为与 RESTful Web 服务交互的理想选择。 这些标志目前定义为:

 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;

中止请求

要放弃请求,只需调用 req.abort() 方法。

超时

有时网络和服务器会“卡住”,接受请求后永远不会回应。 设置超时以避免请求永久等待。

  • req.timeout({deadline:ms})req.timeout(ms)(其中ms是毫秒数> 0)为整个请求(包括所有重定向)设置完成的最后期限.。如果在这段时间内没有完全下载响应,请求将被中止。
  • req.timeout({response:ms}) 设置等待来自服务器的第一个字节的最大时间, 但并不限制整个下载可以花费多长时间。响应超时应比服务器响应所需的时间要长数秒,因为它还包括进行DNS查找,TCP / IP和TLS连接的时间。

你应该使用 deadlineresponse 超时。 通过这种方式,你可以使用短暂的响应超时来快速检测到无响应的网络,并且可以在较慢的但可靠的网络上为下载提供时间。

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(function(res) {
    if (err.timeout) { /* timed out! */ }
  });

超时错误具有 .timeout 属性。

认证

在 Node 和浏览器中,通过 .auth() 方法提供的 auth 可用:

request
  .get('http://local')
  .auth('tobi', 'learnboost')
  .then(callback);

Node 客户端中,基本身份验证可以在URL中作为“user:pass”:

request.get('http://tobi:learnboost@local').then(callback);

默认情况下只使用 Basic auth。 在浏览器中,你可以添加 `{type:'auto'} 来启用浏览器内置的所有方法(Digest,NTLM等):

request.auth('digest', 'secret', {type:'auto'})

重定向 (Following redirects)

默认情况下最多会有5个重定向,但是你可以用 res.redirects(n) 方法指定:

request
  .get('/some.png')
  .redirects(2)
  .then(callback);

代理全局状态

保存cookies

在Node中,SuperAgent 默认不保存 cookie,但是你可以使用 .agent() 方法创建一个保存 cookie 的SuperAgent 副本。 每个副本都有一个单独的 cookie 。

const agent = request.agent();
agent
  .post('/login')
  .then(() => {
    return agent.get('/cookied-page');
  });

在浏览器中,Cookie 由浏览器自动管理,因此 .agent() 不会隔离cookie。

多个请求的默认选项

代理程序上调用的常规请求方法 (.use().set().auth())将用作该代理程序发出的所有请求的默认值。

const agent = request.agent()
  .use(plugin)
  .auth(shared);

await agent.get('/with-plugin-and-auth');
await agent.get('/also-with-plugin-and-auth');

管道数据

Node客户端允许您将数据传入和传出请求。 例如,传递一个文件的内容作为请求:

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);

请注意,当您管道请求时,superagent 会使用 chunked transfer encoding 发送管道数据,而不是所有服务器都支持(例如,Python WSGI服务器)。

或者将响应传递给一个文件:

const stream = fs.createWriteStream('path/to/my.json');
const req = request.get('/some.json');
req.pipe(stream);

请注意,您应该 尝试管道 .end()Response 对象的结果:

// Don't do either of these:
const stream = getAWritableStream();
const req = request
  .get('/some.json')
  // this pipes garbage to the stream and fails in unexpected ways
  .end((err, response) => response.pipe(stream))
const req = request
  .get('/some.json')
  .end()
  // this is also unsupported, .pipe calls .end for you.
  .pipe(stream);

在superagent的 未来版本 中,不正确地调用pipe()将会失败。

多部分请求

SuperAgent 对于提供 .attach().field() 方法的 building 多部分请求也非常给力。

当你使用 .field() 或者 .attach() 时,你不能使用 .send() 而你 不能 设置 'Content-Type'(正确的类型将会被(自动)设置)。

发送文件

要发送文件,请使用 .attach(name, [file], [options])。 您可以通过多次调用 .attach 来附加多个文件。 参数是:

  • name — 表单字段名称
  • file — 带有文件路径的字符串或者“Blob”/“Buffer”对象
  • options — (可选) 用自定义文件名字符串或者“{filename:string}”对象。 在Node中,还支持{contentType:'mime / type'}。 在浏览器中,用相应的类型创建一个“Blob”。

request
  .post('/upload')
  .attach('image1', 'path/to/felix.jpeg')
  .attach('image2', imageBuffer, 'luna.jpeg')
  .field('caption', 'My cats')
  .then(callback);

字段值

就像HTML中的表单字段一样,你可以用 .field(name,value).field({name:value}) 来设置字段值。 假设你想用你的名字和电子邮件上传几张图片,你的请求可能是这样的:

 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);

压缩

节点客户端支持压缩响应,最重要的是,你不必做任何事情!它能用。

缓存响应

要强制缓存响应主体为 res.text,你可以调用 req.buffer()。 要撤消文本响应的默认缓存,例如 “text / plain”,“text / html”等,你可以调用 req.buffer(false)

当缓冲提供 res.buffered 标志时,你可以使用它来处理同一个回调中的缓存和无缓存响应。

CORS

出于安全原因,浏览器将阻止跨源请求,除非服务器选择使用CORS标头。 浏览器也会做额外的
OPTIONS 请求来检查服务器允许的HTTP头和方法。 阅读更多关于CORS

The .withCredentials() method enables the ability to send cookies from the origin, however only when Access-Control-Allow-Origin is not a wildcard (""), and Access-Control-Allow-Credentials is "true".
.withCredentials()方法使得能够从源站发送cookie,但是只有当'Access-Control-Allow-Origin'不是通配符(“
”)和Access-Control-Allow-Credentials 是 "true”时。

request
  .get('http://api.example.com:4001/')
  .withCredentials()
  .then(function(res) {
    assert.equal(200, res.status);
    assert.equal('tobi', res.text);
  })

错误处理

你的回调函数将始终传递两个参数:错误和响应。 如果没有错误发生,第一个参数将为null:

request
 .post('/upload')
 .attach('image', 'path/to/tobi.png')
 .then(function(res) {

 });

当你监听的时候,"error" 事件将被触发:

request
  .post('/upload')
  .attach('image', 'path/to/tobi.png')
  .on('error', handle)
  .then(function(res) {

  });

请注意,superagent默认考虑 4xx 和 5xx 响应(以及未处理的 3xx 响应)错误。 例如,如果你得到一个304 Not modified403 Forbidden500 Internal server error的响应,这个状态信息可以通过err.status获得。 来自这样的响应的错误还包含具有在 “响应属性” 中提及的所有属性的“err.response”字段。 库以这种方式处理想要成功响应和将HTTP错误状态码视为错误的常见情况,同时仍允许围绕特定错误条件的定制逻辑。

网络故障,超时以及其他不产生响应的错误将不包含“err.status”或“err.response”字段。

如果你希望处理404或其他HTTP错误响应,则可以查询“err.status”属性。 当发生HTTP错误(4xx或5xx响应)时,res.error属性是一个Error对象,这允许你执行如下检查:

if (err && err.status === 404) {
  alert('oh no ' + res.body.message);
}
else if (err) {
  // all other error types we handle generically
}

或者,您可以使用.ok(callback)方法来决定响应是否是错误的。 如果响应应该被解释为成功,则对“ok”函数的回调将得到一个响应并返回“true”。

request.get('/404')
  .ok(res => res.status < 500)
  .then(response => {
    // reads 404 page as a successful response
  })

进度跟踪

SuperAgent在上传和下载大文件时触发“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
    } */
  })
  .end()

Promise 和 Generator 支持

SuperAgent 的请求是一个“可接受的”对象,它与 JavaScript promise 和 async /await 语法兼容。 如果你使用promises,请勿调用 .end()

co 这样的库或 koa 这样的 web 框架可以在任何 SuperAgent 方法上 "yield" :

const req = request
  .get('http://local')
  .auth('tobi', 'learnboost');
const res = yield req;

请注意,SuperAgent 期望全局 Promise 对象存在。 您需要在 Internet Explorer 或 Node.js 0.10 中使用 polyfill 来使用 promise 。

浏览器和节点版本

SuperAgent 有两个实现:一个用于Web浏览器(使用XHR),一个用于Node.JS(使用核心http模块)。 默认情况下,Browserify和WebPack将选择浏览器版本。

如果要使用WebPack编译Node.JS的代码,您必须在其配置中指定node target

在 electron 中使用浏览器版本

Electron 开发人员报告,如果您希望使用浏览器版本的 SuperAgent 而不是Node版本,则可以使用 require('superagent / superagent')。 您的请求现在将显示在Chrome开发人员工具“网络”标签中。 请注意,此环境不包含在自动化测试套件中,并且不受官方支持。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment