自定义Angular2装饰器,用于创建URLSearchParams

时间:2016-12-08 16:36:29

标签: angular typescript angular2-http

我正在使用angular 2创建一个api服务,并创建了一些装饰器来帮助简化类接口以及一些可重用的功能。

我希望我的所有服务方法都能获取一个镜像http请求查询参数的请求对象映射。

例如:

const request: SomeInterface = {
    param: 'value',
    otherParam: 'otherValue',
};

将传递给一个类方法,该方法将这些键/值对用作http请求中的查询字符串参数。

以最简单的形式,我想要这样的事情发生。此示例将不会执行,因为SomeInterface不是Angular对搜索属性所期望的类型。

public getSomething(search: SomeInterface) {
    this.http.get(url, {
        search: search,
    });
}

我创建了两个装饰器来完成将对象转换为URLSearchParams的实例。

import { URLSearchParams } from '@angular/http';

export function UrlSearchParams() {
    return function UrlSearchParams(target: any, methodName: string, index: number) {
        const metadataKey = `__urlSearchParams_${methodName}__`;
        target[metadataKey] = [index];
    };
};

export function NgServiceMethod() {
    return function NgServiceMethod(target, methodName, descriptor) {

        if (!descriptor) {
            descriptor = Object.getOwnPropertyDescriptor(target, methodName);
        }
        const originalMethod = descriptor.value;

        descriptor.value = function (...args: any[]) {
            const metadataKey = `__urlSearchParams_${methodName}__`;
            const parameter = target[metadataKey];
            const searchParams = new URLSearchParams();
            const request = args[parameter];

            for (const key in request) {
                if (request.hasOwnProperty(key)) {
                    searchParams.set(key, key);
                }
            }
            args[parameter] = searchParams;

            return originalMethod.apply(this, args);
        };

        return descriptor;
    };
};

以下是它的实例。

import { NgServiceMethod, UrlSearchParams } from '../shared/express/url-search-params.decorator';
import * as process from 'process';
import { SubmissionsRequest } from './submissions-request.model';
import { Injectable } from '@angular/core';
import { Http, URLSearchParams, Headers } from '@angular/http';

@Injectable()
export class SubmissionsApiService {

    private submissionsApiUrl: string = '/social-submissions';

    constructor(private http: Http) { ; }

    @NgServiceMethod()
    public listSubmissions( @UrlSearchParams() submissionsRequest: SubmissionsRequest) {
        const headers = new Headers({
            'X-API-KEY': process.env.SUBMISSIONS_API_KEY,
        });

        return this.http.get(this.submissionsApiUrl, {
            search: submissionsRequest as URLSearchParams,
            headers: headers,
        });
    }
}

这很有效。然而,我正在努力解决一些挑剔的问题。

  1. 我希望服务方法签名接受带有请求对象接口的参数。在工作示例的情况下,SubmissionsRequest的实例。不幸的是,实际传递函数的是URLSearchParams的一个实例,因为它被UrlSearchParams装饰器取代。

    1. 由于上述原因,我必须在实际的submissionsRequest电话中使用URLSearchParamshttp.get
  2. 一切正常,但这会产生误导,因为我说方法签名中的submissionsRequest类型为SubmissionsRequest,但实际情况是URLSearchParams类型。

    我想我不希望服务的消费者不必担心传递URLSearchParams的实例而宁愿在服务中做这项工作,但我也不想要我的服务方法使用错误的类型。

    关于如何调和此问题的任何建议或想法?

0 个答案:

没有答案