NativeScript 网络请求 #

网络请求概述 #

NativeScript 提供了多种方式进行网络请求,包括内置的 Http 模块和第三方库。

text
┌─────────────────────────────────────────────────────────────┐
│                    网络请求方式                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  内置模块                                                    │
│  ├── @nativescript/core/http    基础 HTTP 请求              │
│  └── fetch API                  标准 Fetch 接口             │
│                                                             │
│  第三方库                                                    │
│  ├── axios                      流行的 HTTP 客户端          │
│  └── Angular HttpClient         Angular HTTP 模块           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

使用 Http 模块 #

基本请求 #

typescript
import { Http } from '@nativescript/core';

// GET 请求
const response = await Http.getJSON<ApiResponse>('https://api.example.com/users');
console.log(response);

// POST 请求
const response = await Http.request({
    url: 'https://api.example.com/users',
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    content: JSON.stringify({
        name: 'John',
        email: 'john@example.com'
    })
});

console.log(response.content.toJSON());

GET 请求 #

typescript
// 简单 GET
const data = await Http.getJSON<User[]>('https://api.example.com/users');

// 带参数 GET
const url = 'https://api.example.com/users?page=1&limit=10';
const data = await Http.getJSON<User[]>(url);

// 带请求头
const response = await Http.request({
    url: 'https://api.example.com/users',
    method: 'GET',
    headers: {
        'Authorization': 'Bearer token',
        'Accept': 'application/json'
    }
});

const data = response.content.toJSON();

POST 请求 #

typescript
// JSON 数据
const response = await Http.request({
    url: 'https://api.example.com/users',
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer token'
    },
    content: JSON.stringify({
        name: 'John',
        email: 'john@example.com'
    })
});

// 表单数据
const response = await Http.request({
    url: 'https://api.example.com/upload',
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    content: 'name=John&email=john@example.com'
});

PUT 请求 #

typescript
const response = await Http.request({
    url: 'https://api.example.com/users/1',
    method: 'PUT',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer token'
    },
    content: JSON.stringify({
        name: 'John Updated',
        email: 'john.updated@example.com'
    })
});

DELETE 请求 #

typescript
const response = await Http.request({
    url: 'https://api.example.com/users/1',
    method: 'DELETE',
    headers: {
        'Authorization': 'Bearer token'
    }
});

文件上传 #

typescript
import { knownFolders, path } from '@nativescript/core';

const file = knownFolders.documents().getFile('image.jpg');

const response = await Http.request({
    url: 'https://api.example.com/upload',
    method: 'POST',
    headers: {
        'Content-Type': 'multipart/form-data'
    },
    content: file
});

使用 Fetch API #

基本用法 #

typescript
// GET 请求
const response = await fetch('https://api.example.com/users');
const data = await response.json();

// POST 请求
const response = await fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer token'
    },
    body: JSON.stringify({
        name: 'John',
        email: 'john@example.com'
    })
});

const data = await response.json();

封装 Fetch #

typescript
// services/api.service.ts
export class ApiService {
    private baseUrl = 'https://api.example.com';
    private token: string;
    
    setToken(token: string) {
        this.token = token;
    }
    
    private async request<T>(
        endpoint: string,
        options: RequestInit = {}
    ): Promise<T> {
        const url = `${this.baseUrl}${endpoint}`;
        
        const headers = {
            'Content-Type': 'application/json',
            ...options.headers
        };
        
        if (this.token) {
            headers['Authorization'] = `Bearer ${this.token}`;
        }
        
        const response = await fetch(url, {
            ...options,
            headers
        });
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        return response.json();
    }
    
    get<T>(endpoint: string): Promise<T> {
        return this.request<T>(endpoint);
    }
    
    post<T>(endpoint: string, data: any): Promise<T> {
        return this.request<T>(endpoint, {
            method: 'POST',
            body: JSON.stringify(data)
        });
    }
    
    put<T>(endpoint: string, data: any): Promise<T> {
        return this.request<T>(endpoint, {
            method: 'PUT',
            body: JSON.stringify(data)
        });
    }
    
    delete<T>(endpoint: string): Promise<T> {
        return this.request<T>(endpoint, {
            method: 'DELETE'
        });
    }
}

使用 Axios #

安装 Axios #

bash
npm install axios

基本用法 #

typescript
import axios from 'axios';

// GET 请求
const response = await axios.get<User[]>('https://api.example.com/users');
console.log(response.data);

// POST 请求
const response = await axios.post<User>('https://api.example.com/users', {
    name: 'John',
    email: 'john@example.com'
});

// 带参数
const response = await axios.get<User[]>('https://api.example.com/users', {
    params: {
        page: 1,
        limit: 10
    }
});

创建实例 #

typescript
import axios, { AxiosInstance } from 'axios';

const api: AxiosInstance = axios.create({
    baseURL: 'https://api.example.com',
    timeout: 10000,
    headers: {
        'Content-Type': 'application/json'
    }
});

// 使用实例
const response = await api.get<User[]>('/users');

请求拦截器 #

typescript
// 请求拦截器
api.interceptors.request.use(
    (config) => {
        const token = getToken();
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);

// 响应拦截器
api.interceptors.response.use(
    (response) => {
        return response.data;
    },
    (error) => {
        if (error.response?.status === 401) {
            // Token 过期,跳转登录
            logout();
        }
        return Promise.reject(error);
    }
);

Angular HttpClient #

配置 HttpClient #

typescript
// app.module.ts
import { HttpClientModule } from '@angular/common/http';

@NgModule({
    imports: [
        NativeScriptModule,
        HttpClientModule
    ]
})
export class AppModule {}

创建服务 #

typescript
// services/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map, catchError } from 'rxjs/operators';

@Injectable({
    providedIn: 'root'
})
export class UserService {
    private apiUrl = 'https://api.example.com';
    
    constructor(private http: HttpClient) {}
    
    getUsers(page: number = 1, limit: number = 10): Observable<User[]> {
        const params = new HttpParams()
            .set('page', page.toString())
            .set('limit', limit.toString());
        
        return this.http.get<ApiResponse<User[]>>(`${this.apiUrl}/users`, { params })
            .pipe(
                map(response => response.data),
                catchError(this.handleError)
            );
    }
    
    getUser(id: number): Observable<User> {
        return this.http.get<User>(`${this.apiUrl}/users/${id}`);
    }
    
    createUser(user: CreateUserDto): Observable<User> {
        return this.http.post<User>(`${this.apiUrl}/users`, user);
    }
    
    updateUser(id: number, user: UpdateUserDto): Observable<User> {
        return this.http.put<User>(`${this.apiUrl}/users/${id}`, user);
    }
    
    deleteUser(id: number): Observable<void> {
        return this.http.delete<void>(`${this.apiUrl}/users/${id}`);
    }
    
    private handleError(error: any): Observable<never> {
        console.error('API Error:', error);
        throw error;
    }
}

使用拦截器 #

typescript
// interceptors/auth.interceptor.ts
import { Injectable } from '@angular/core';
import {
    HttpRequest,
    HttpHandler,
    HttpEvent,
    HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    intercept(
        request: HttpRequest<any>,
        next: HttpHandler
    ): Observable<HttpEvent<any>> {
        const token = getToken();
        
        if (token) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${token}`
                }
            });
        }
        
        return next.handle(request);
    }
}
typescript
// app.module.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './interceptors/auth.interceptor';

@NgModule({
    providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: AuthInterceptor,
            multi: true
        }
    ]
})
export class AppModule {}

错误处理 #

统一错误处理 #

typescript
// services/error-handler.service.ts
import { Injectable } from '@angular/core';

@Injectable({
    providedIn: 'root'
})
export class ErrorHandlerService {
    handle(error: any): void {
        let message = 'An error occurred';
        
        if (error.status) {
            switch (error.status) {
                case 400:
                    message = 'Bad request';
                    break;
                case 401:
                    message = 'Unauthorized';
                    this.handleUnauthorized();
                    break;
                case 403:
                    message = 'Forbidden';
                    break;
                case 404:
                    message = 'Not found';
                    break;
                case 500:
                    message = 'Server error';
                    break;
                default:
                    message = `Error: ${error.status}`;
            }
        } else if (error.message) {
            message = error.message;
        }
        
        this.showError(message);
    }
    
    private handleUnauthorized(): void {
        // 清除 token,跳转登录
    }
    
    private showError(message: string): void {
        // 显示错误提示
        console.error(message);
    }
}

重试机制 #

typescript
import { retry, retryWhen, delay, scan } from 'rxjs/operators';

// 简单重试
this.http.get<User[]>('/users')
    .pipe(
        retry(3)
    );

// 自定义重试
this.http.get<User[]>('/users')
    .pipe(
        retryWhen(errors =>
            errors.pipe(
                scan((count, error) => {
                    if (count >= 3) {
                        throw error;
                    }
                    return count + 1;
                }, 0),
                delay(1000)
            )
        )
    );

网络状态检测 #

检测网络连接 #

typescript
import { ConnectionType, connectivity } from '@nativescript/core';

// 获取当前连接类型
const connectionType = connectivity.getConnectionType();

switch (connectionType) {
    case ConnectionType.wifi:
        console.log('WiFi connected');
        break;
    case ConnectionType.mobile:
        console.log('Mobile network connected');
        break;
    case ConnectionType.none:
        console.log('No network connection');
        break;
}

// 监听网络变化
connectivity.startMonitoring((newConnectionType: number) => {
    switch (newConnectionType) {
        case ConnectionType.wifi:
            console.log('WiFi connected');
            break;
        case ConnectionType.mobile:
            console.log('Mobile network connected');
            break;
        case ConnectionType.none:
            console.log('No network connection');
            break;
    }
});

// 停止监听
connectivity.stopMonitoring();

离线处理 #

typescript
// services/offline.service.ts
import { Injectable } from '@angular/core';
import { ConnectionType, connectivity } from '@nativescript/core';

@Injectable({
    providedIn: 'root'
})
export class OfflineService {
    private isOnline: boolean;
    
    constructor() {
        this.isOnline = connectivity.getConnectionType() !== ConnectionType.none;
        
        connectivity.startMonitoring((type) => {
            this.isOnline = type !== ConnectionType.none;
        });
    }
    
    get online(): boolean {
        return this.isOnline;
    }
    
    async requestWithOffline<T>(
        onlineRequest: () => Promise<T>,
        offlineFallback?: () => Promise<T>
    ): Promise<T> {
        if (this.isOnline) {
            return onlineRequest();
        } else if (offlineFallback) {
            return offlineFallback();
        } else {
            throw new Error('No network connection');
        }
    }
}

最佳实践 #

API 服务封装 #

typescript
// services/api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

interface ApiResponse<T> {
    data: T;
    message: string;
    status: number;
}

@Injectable({
    providedIn: 'root'
})
export class ApiService {
    private baseUrl = 'https://api.example.com/api/v1';
    
    constructor(private http: HttpClient) {}
    
    get<T>(endpoint: string, params?: any): Observable<T> {
        return this.http.get<ApiResponse<T>>(`${this.baseUrl}${endpoint}`, { params })
            .pipe(
                map(response => response.data)
            );
    }
    
    post<T>(endpoint: string, body?: any): Observable<T> {
        return this.http.post<ApiResponse<T>>(`${this.baseUrl}${endpoint}`, body)
            .pipe(
                map(response => response.data)
            );
    }
    
    put<T>(endpoint: string, body?: any): Observable<T> {
        return this.http.put<ApiResponse<T>>(`${this.baseUrl}${endpoint}`, body)
            .pipe(
                map(response => response.data)
            );
    }
    
    delete<T>(endpoint: string): Observable<T> {
        return this.http.delete<ApiResponse<T>>(`${this.baseUrl}${endpoint}`)
            .pipe(
                map(response => response.data)
            );
    }
}

请求取消 #

typescript
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

@Component({
    // ...
})
export class UserComponent implements OnInit, OnDestroy {
    private destroy$ = new Subject<void>();
    
    constructor(private userService: UserService) {}
    
    ngOnInit() {
        this.userService.getUsers()
            .pipe(
                takeUntil(this.destroy$)
            )
            .subscribe(users => {
                // 处理数据
            });
    }
    
    ngOnDestroy() {
        this.destroy$.next();
        this.destroy$.complete();
    }
}

下一步 #

现在你已经掌握了网络请求,接下来学习 本地存储,了解如何存储本地数据!

最后更新:2026-03-29