- 版本:3.0.0
- GitHub:
- NPM: https://npmjs.net.cn/package/nativescript-apiclient
- 下载
- 昨日: 0
- 上周: 1
- 上个月: 59
NativeScript API客户端
一个NativeScript模块,用于简单调用基于HTTP的API。
NativeScript 工具箱
此模块是nativescript-toolbox的一部分。
许可证
平台
- Android
- iOS
安装
在你的应用程序项目中运行以安装模块。
tns plugin add nativescript-apiclient
示例
快速入门
请查看plugin/index.ts或使用你的IDE的"IntelliSense"来了解其工作方式。
否则...
用法
导入
import ApiClient = require("nativescript-apiclient");
示例
import ApiClient = require("nativescript-apiclient");
import HTTP = require("http");
interface IUser {
displayName?: string;
id?: number;
name?: string;
}
var client = ApiClient.newClient({
baseUrl: "https://api.example.com/users",
route: "{id}",
});
client.beforeSend(function(opts: HTTP.HttpRequestOptions, tag: any) {
console.log("Loading user: " + tag);
// prepare the request here
})
.clientError(function(result: ApiClient.IApiClientResult) {
// handle all responses with status code 400 to 499
})
.serverError(function(result: ApiClient.IApiClientResult) {
// handle all responses with status code 500 to 599
})
.success(function(result: ApiClient.IApiClientResult) {
// handle all responses with that were NOT
// handled by 'clientError()' and 'serverError()'
//
// especially with status code less than 400 and greater than 599
var user = result.getJSON<IUser>();
})
.error(function(err: ApiClient.IApiClientError) {
// handle API client errors
})
.completed(function(ctx: ApiClient.IApiClientCompleteContext) {
// invoked after "result" and "error" actions
});
var credentials = new ApiClient.BasicAuth("Marcel", "p@ssword!");
for (var userId = 1; userId <= 100; userId++) {
// start a GET request
//
// [GET] https://api.example.com/users/{id}?ver=1.6.6.6
client.get({
authorizer: credentials,
// request headers
headers: {
'X-MyHeader-TM': '5979',
'X-MyHeader-MK': '23979'
},
// URL parameters
params: {
ver: '1.6.6.6'
},
// route parameters
routeParams: {
id: userId.toString() // {id}
},
// global value for all callbacks
tag: userId
});
}
路由
路由是基本URL的后缀。
您可以在该路由中定义一个或多个参数,这些参数在启动请求时将被替换。
如果您创建一个客户端如这样
var client = ApiClient.newClient({
baseUrl: "https://api.example.com/users",
route: "{id}/{resource}",
});
并启动一个请求如这样
client.get({
routeParams: {
id: "5979", // {id}
resource: "profile" // {resource}
}
});
客户端将调用以下URL
[GET] https://api.example.com/users/5979/profile
参数值也可以是函数,这意味着该函数返回的值将用作值
var getUserId = function() : string {
// load the user ID from somewhere
};
client.get({
routeParams: {
id: getUserId, // {id}
resource: "profile" // {resource}
}
});
函数必须具有以下结构
function (paramName: string, routeParams: any, match: string, formatExpr: string, funcDepth: string) : any {
return <THE-VALUE-TO-USE>;
}
名称 | 描述 |
---|---|
paramName | 参数的名称。对于{id} ,这将变为id |
routeParams | 提交的参数列表及其值。重要:确保将值作为字符串返回!否则,您可能无法将值转换为URL部分。 |
match | 参数的完整(未处理的)表达式。 |
formatExpr | 参数的可选格式表达式。对于{id:number} ,这将变为number 。 |
funcDepth | 此值最初为0 。如果您在该函数中再次返回一个函数,此值将增加,直到您停止返回函数。 |
格式化值
跟随一个:
字符,路由参数定义可以额外包含一个"格式表达式"。
这些表达式可以帮助您解析和格式化参数值。
为此,首先在客户端中定义一个所谓的"格式提供者"回调
client.addFormatProvider((ctx : ApiClient.IFormatProvider) => {
var toStringSafe = function() : string {
return ctx.value ? ctx.value.toString() : "";
};
if (ctx.expression === "upper") {
ctx.handled = true;
return toStringSafe().toUpperCase(); // the new value
}
else if (ctx.expression === "number") {
var n = parseInt(toStringSafe().trim());
if (isNaN(n)) {
throw "'" + ctx.value + "' is NOT a number!";
}
ctx.handled = true;
return n.toString();
}
});
在此,我们定义了两个表达式upper
(转换为大写字母)和number
(确保有一个有效的数字)。
要使用它们,您可以定义一个路由如下
{id:number}/{resource:upper}
现在,如果您设置客户端
var client = ApiClient.newClient({
baseUrl: "https://api.example.com/users",
route: "{id:number}/{resource:upper}",
});
并启动一个请求如这样
client.get({
routeParams: {
id: "5979",
resource: "profile"
}
});
客户端将调用以下URL
[GET] https://api.example.com/users/5979/PROFILE
ctx
对象在addFormatProvider()
的格式提供者调用中具有以下结构
interface IFormatProviderContext {
/**
* Gets the format expression.
*/
expression: string;
/**
* Gets if the expression has been handled or not.
*/
handled: boolean;
/**
* Gets the underlying (unhandled) value.
*/
value: any;
}
授权
当您启动请求时,您可以提交一个可选的IAuthorizer
对象
interface IAuthorizer {
/**
* Prepares a HTTP request for authorization.
*
* @param {HTTP.HttpRequestOptions} reqOpts The request options.
*/
prepare(reqOpts: HTTP.HttpRequestOptions);
}
插件提供以下实现
AggregateAuthorizer
var authorizer = new ApiClient.AggregateAuthorizer();
authorizer.addAuthorizers(new ApiClient.BasicAuth("Username", "Password"),
new ApiClient.BearerAuth("MySecretToken"));
BasicAuth
var authorizer = new ApiClient.BasicAuth("Username", "Password");
BearerAuth
var authorizer = new ApiClient.BearerAuth("MySecretToken");
OAuth
var authorizer = new ApiClient.OAuth("MySecretToken");
authorizer.setField('oauth_field1', 'field1_value');
authorizer.setField('oauth_field2', 'field2_value');
TwitterOAuth
var authorizer = new ApiClient.TwitterOAuth("<CONSUMER_KEY>", "<CONSUMER_SECRET>",
"<TOKEN>", "<TOKEN_SECRET>");
请求
GET
// ?TM=5979&MK=23979
client.get({
params: {
TM: '5979',
MK: '23979'
}
});
POST
client.post({
content: {
id: 5979,
name: "Tanja"
},
type: ApiClient.HttpRequestType.JSON
});
PUT
client.put({
content: '<user><id>23979</id><name>Marcel</name></user>',
type: ApiClient.HttpRequestType.XML
});
PATCH
client.patch({
content: '<user id="241279"><name>Julia</name></user>',
type: ApiClient.HttpRequestType.XML
});
DELETE
client.delete({
content: {
id: 221286
},
type: ApiClient.HttpRequestType.JSON
});
自定义
client.request("FOO", {
content: {
TM: 5979,
MK: 23979
},
type: ApiClient.HttpRequestType.JSON
});
日志记录
如果您想在结果/错误回调中记录日志,您必须在客户端中定义一个或多个日志操作
var client = ApiClient.newClient({
baseUrl: "https://example.com/users",
route: "{id}",
});
client.addLogger(function(msg : ApiClient.ILogMessage) {
console.log("[" + ApiClient.LogSource[msg.source] + "]: " + msg.message);
});
每个操作接收以下类型的一个对象
interface ILogMessage {
/**
* Gets the category.
*/
category: LogCategory;
/**
* Gets the message value.
*/
message: any;
/**
* Gets the priority.
*/
priority: LogPriority;
/**
* Gets the source.
*/
source: LogSource;
/**
* Gets the tag.
*/
tag: string;
/**
* Gets the timestamp.
*/
time: Date;
}
现在您可以开始记录回调中的登录操作
client.clientError(function(result : ApiClient.IApiClientResult) {
result.warn("Client error: " + result.code);
})
.serverError(function(result : ApiClient.IApiClientResult) {
result.err("Server error: " + result.code);
})
.success(function(result : ApiClient.IApiClientResult) {
result.info("Success: " + result.code);
})
.error(function(err : ApiClient.IApiClientError) {
result.crit("API CLIENT ERROR!: " + err.error);
})
.completed(function(ctx : ApiClient.IApiClientCompleteContext) {
result.dbg("Completed action invoked.");
});
使用 ILogger
接口的 IApiClientResult
、IApiClientError
和 IApiClientCompleteContext
对象
interface ILogger {
/**
* Logs an alert message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
alert(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs a critical message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
crit(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs a debug message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
dbg(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs an emergency message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
emerg(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs an error message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
err(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs an info message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
info(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs a message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogCategory} [category] The optional log category. Default: LogCategory.Debug
* @param {LogPriority} [priority] The optional log priority.
*/
log(msg : any, tag?: string,
category?: LogCategory, priority?: LogPriority) : ILogger;
/**
* Logs a notice message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
note(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs a trace message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
trace(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
/**
* Logs a warning message.
*
* @param any msg The message value.
* @param {String} [tag] The optional tag value.
* @param {LogPriority} [priority] The optional log priority.
*/
warn(msg : any, tag?: string,
priority?: LogPriority) : ILogger;
}
URL 参数
您可以为 URL 定义额外的参数。
如果您创建一个客户端如这样
var client = ApiClient.newClient({
baseUrl: "https://api.example.com/users"
});
并启动一个请求如这样
client.get({
params: {
id: '23979',
resource: "profile"
}
});
客户端将调用该 URL
[GET] https://api.example.com/users?id=23979&resource=profile
类似于路由参数,您也可以使用函数来定义 URL 参数
var getUserId = function() : string {
// load the user ID from somewhere
};
client.get({
params: {
id: getUserId, // {id}
resource: "profile" // {resource}
}
});
函数必须具有以下结构
function (paramName: string, index: number, funcDepth: string) : any {
return <THE-VALUE-TO-USE>;
}
名称 | 描述 |
---|---|
paramName | 参数的名称。对于{id} ,这将变为id |
索引 | 处理 URL 参数的零基于索引。 |
funcDepth | 此值最初为0 。如果您在该函数中再次返回一个函数,此值将增加,直到您停止返回函数。 |
重要提示:还建议将/返回字符串作为参数值,以防止在将值转换为 URL 字符串时出现问题。
响应
回调
简单
client.success(function(result : ApiClient.IApiClientResult) {
// handle any response
});
result
对象具有以下结构
interface IApiClientResult extends ILogger {
/**
* Gets the underlying API client.
*/
client: IApiClient;
/**
* Gets the HTTP response code.
*/
code: number;
/**
* Gets the raw content.
*/
content: any;
/**
* Gets the underlying (execution) context.
*/
context: ApiClientResultContext;
/**
* Gets the response headers.
*/
headers: HTTP.Headers;
/**
* Returns the content as wrapped AJAX result object.
*
* @return {IAjaxResult<TData>} The ajax result object.
*/
getAjaxResult<TData>() : IAjaxResult<TData>;
/**
* Returns the content as file.
*
* @param {String} [destFile] The custom path of the destination file.
*
* @return {FileSystem.File} The file.
*/
getFile(destFile?: string) : FileSystem.File;
/**
* Tries result the content as image source.
*/
getImage(): Promise<Image.ImageSource>;
/**
* Returns the content as JSON object.
*/
getJSON<T>() : T;
/**
* Returns the content as string.
*/
getString() : string;
/**
* Gets the information about the request.
*/
request: IHttpRequest;
/**
* Gets the raw response.
*/
response: HTTP.HttpResponse;
}
错误
client.error(function(err : ApiClient.IApiClientError) {
// handle an HTTP client error here
});
err
对象具有以下结构
interface IApiClientError extends ILogger {
/**
* Gets the underlying client.
*/
client: IApiClient;
/**
* Gets the context.
*/
context: ApiClientErrorContext;
/**
* Gets the error data.
*/
error: any;
/**
* Gets or sets if error has been handled or not.
*/
handled: boolean;
/**
* Gets the information about the request.
*/
request: IHttpRequest;
}
条件回调
您可以定义任何类型的条件的回调。
一个通用的方法是使用 if()
方法
client.if(function(result : IApiClientResult) : boolean {
// invoke if 'X-My-Custom-Header' is defined
return undefined !== result.headers["X-My-Custom-Header"];
},
function(result : IApiClientResult) {
// handle the response
});
如果没有条件匹配,则使用 success()
方法定义的回调。
对于特定的状态码,您可以使用 ifStatus()
方法
client.ifStatus((statusCode) => statusCode === 500,
function(result : IApiClientResult) {
// handle the internal server error
});
或简短
client.status(500,
function(result : IApiClientResult) {
// handle the internal server error
});
简写回调
client.clientError(function(result : ApiClient.IApiClientResult) {
// handle status codes between 400 and 499
});
client.ok(function(result : ApiClient.IApiClientResult) {
// handle status codes with 200, 204 or 205
});
client.serverError(function(result : ApiClient.IApiClientResult) {
// handle status codes between 500 and 599
});
以下方法也受支持
名称 | 描述 |
---|---|
badGateway | 处理状态码为 502 的请求。 |
badRequest | 处理状态码为 400 的请求。 |
clientOrServerError | 处理状态码在 400 和 599 之间的请求。 |
conflict | 处理状态码为 409 的请求。 |
forbidden | 处理状态码为 403 的请求。 |
gatewayTimeout | 处理状态码为 504 的请求。 |
gone | 处理状态码为 410 的请求。 |
informational | 处理状态码在 100 和 199 之间的请求。 |
insufficientStorage | 处理状态码为 507 的请求。 |
internalServerError | 处理状态码为 500 的请求。 |
locked | 处理状态码为 423 的请求。 |
methodNotAllowed | 处理状态码为 405 的请求。 |
notFound | 处理状态码为 404 的请求。 |
notImplemented | 处理状态码为 501 的请求。 |
partialContent | 处理状态码为 206 的请求。 |
payloadTooLarge | 处理状态码为 413 的请求。 |
redirection | 处理状态码在 300 和 399 之间的请求。 |
serviceUnavailable | 处理状态码为 503 的请求。 |
succeededRequest | 处理状态码在 200 和 299 之间的请求。 |
tooManyRequests | 处理状态码为 429 的请求。 |
unauthorized | 处理状态码为 401 的请求。 |
unsupportedMediaType | 处理状态码为 415 的请求。 |
uriTooLong | 处理状态码为 414 的请求。 |