3.0.31 • Published 5 years ago

modelproxy v3.0.31

Weekly downloads
6
License
MIT
Repository
github
Last release
5 years ago

modelproxy

1. 解决了什么问题

通过配置文件,自动生成接口的调用方法,参考modelproxy。 在具体的实践过程中,总觉得很多的不满意,修改一下使得满足更多的场景。

小程序登陆流程

上图为小程序的登陆流程。假设我们要发起请求,必须获取上图中的自定义登陆态,而且还需要判定登陆是否过期。

假设我们发起一次接口请求,如何自动登陆,添加自定义登录态数据:

const authCompose = (reload=false)=> new modelProxy.Compose(async (ctx, next) => {
    // 登陆来获取code,并进行缓存
    // 这里对wx的api进行了统一封装,参考自定义engine
    const data = await proxy.execute("wx","login",{
        settings:{
            cache:true,
            reload
        },
        instance:{
            engine:"wx"
        }
    });

    ctx.result = data.data.code;

    await next();
}, async (ctx, next) => {
    // 用code换取 token,并进行缓存
    const data = await proxy.execute("test","login",{
        params:{code: ctx.result},
        settings:{
            cache,
            reload
        }
    });

    ctx.result = data.data.token;

    await next();
}, async (ctx, next) => {
    let {settings={}} = ctx.executeInfo;
    let {header={}} = settings;

    // 将token加入到请求头
    header["token"] = ctx.result;

    ctx.executeInfo.settings = {
        ...settings,
        header
    };

    await next();
}, async (ctx, next) => {
    // 进行session的校验
    // 这里对wx的api进行了统一封装,参考自定义engine
    const data = await proxy.execute("wx","checkSession",{
        instance:{
            engine:"wx"
        }
    });

    // 登陆过期
    if(ctx.isError){
        ctx.result = await proxy.execute(ctx.instance.ns,ctx.instance.key,{
            ...ctx.executeInfo,
            // 强制刷新缓存
            before:authCompose(true)
        });

        return next("abort");
    }

    await next();
})

// 这里获取登陆的用户信息,不用考虑登陆的问题
const userInfo = await proxy.execute("test", "userInfo", {
    before: authCompose()
});

2. 安装和依赖

 npm install modelproxy

3. API

4. ModelProxy

constructor

构造函数

    var proxy = new ModelProxy();

loadConfig

载入接口配置信息,载入后即可调用接口,返回ModelProxy对象;

事例配置:

proxy.loadConfig({
    "key": "test",
    "title": "p-uc",
    "engine": "default",
    "mockDir": "/mocks/",
    "states": {
        "dev": "http://www.baidu.com"
    },
    "state": "dev",
    "interfaces": [{
        "key": "article",
        "title": "文章接口",
        "method": "GET",
        "path": "/articles"
    }, {
        "key": "login",
        "title": "登陆接口",
        "method": "POST",
        "path": "/passport/login",
        "engine": "default",
        "config": {
            "test": "test-1"
        }
    }]
});

addEngines

加入engines,默认只有default一个engine。

proxy.addEngines({
    "wx": (new WxAppEngine()).init()
});

实例engine,本例中是一个微信小程序的engine。

import { ModelProxy,BaseEngine } from 'modelproxy';
import URLSearchParams from 'url-search-params';

export class WxAppEngine extends BaseEngine {
    init() {
        this.use(async (ctx, next) => {
            const app = getApp();
            const { instance, executeInfo = {}, settings = {} } = ctx;
            let { header = {} } = settings;

            try{
                ctx.result = await app.wxPromisify(wx.request)({
                    url: this.getFullPath(instance, executeInfo),
                    data: executeInfo.data,
                    header: header || {},
                    method: instance.method
                });
            }catch(e){
                ctx.isError=true;
                ctx.err = e;
            }
            // 如果有错误,则调用下一个中间件,如果没错误则停止中间件的执行
            await next(!ctx.isError ? "abort" : null);
        });

        this.use(async (ctx,next)=>{
            wx.showToast({
                title: ctx.err.message,
                icon: "error"
            });

            console.group("接口调用错误!",new Date());
            console.error(ctx.err);
            console.groupEnd();

            throw ctx.err;
        });

        return this;
    }

    async proxy(instance, options) {
        const fn = this.callback(() => { });
        const ctx = {
            instance: instance,
            executeInfo: options,
        };

        await fn(ctx);

        return ctx.result;
    }
}

execute

调用一个接口。返回一个promise对象;

    proxy.execute("test","login",{
        data:{
            username:"nick",
            password:"111111"
        }
    });

executeAll

调用多个接口。返回一个promise对象;

    proxy.executeAll({
        login: login.get.bind(login, null, {
            params: {
                tag: "nora"
            }
        }),
        article: article.delete.bind(article, 1)
    }).then(console.log);

race

调用多个接口,返回第一个返回的接口的数据,返回Promise;

    proxy.race([
        login.get.bind(login, null, {
            params: {
                tag: "nora"
            }
        }),
        article.delete.bind(article, 1)
    ]).then(console.log);

getNs

获取一个命名空间,空间中存放的是接口。不同命名空间中使用不同的域名,所以同域名的接口可以配置在同一个配置文件中。返回一个InterfaceFactory对象。

    proxy.getNs("test");

mixin

合并多个接口,生成rest风格的接口。返回一个方法。

    const modelproxy = require("./");
    const proxy = new modelproxy.ModelProxy();

    proxy.loadConfig({
        "key": "test",
        "engine": "default",
        "states": {
            "dev": "http://www.baidu.com"
        },
        "state": "dev",
        "interfaces": [{
            "key": "articles",
            "title": "文章接口",
            "method": "GET",
            "path": "/articles"
        }, {
            "key": "users",
            "title": "用户列表",
            "method": "GET",
            "path": "/users",
            "engine": "default"
        }]
    }, {});

    const userArticles = proxy.mixin("test", "users", "articles")(1);
    const users = proxy.mixin("test", "users")();

    console.log(userArticles.path); // /users/1/articles

    userArticles.get(5); // GET /users/1/articles/5
    users.get(); // GET /users

Cache

缓存设置;

  • cacheDec: (func:()=>Promise,key,settings)=> () => Promise;
  • settings:
    • cache: 是否需要缓存
    • reload: 强制失效缓存
    • expire: 缓存过期时间(单位毫秒)
 cacheDec(()=>{
     return Promise.resolve(123);
 },"testKey",{cache: true,reload:true,expire:10})

5. InterfaceFactory

get

通过get调用接口。这里会覆盖配置文件中配置的method属性。

    // 获取文章列表
    proxy.getNs("test").get("article").get();
    // 发送请求 GET http://www.baidu.com/articles

getOne

通过get调用接口。这里会覆盖配置文件中配置的method属性。

    // 获取文章的详情,id为1
    proxy.getNs("test").get("article").getOne(1);
    // 发送请求 GET http://www.baidu.com/articles/1

post

通过post调用接口。这里会覆盖配置文件中配置的method属性。

    proxy.getNs("test").get("article").post({
        data:{...}
    });
    // 发送请求 POST http://www.baidu.com/articles

delete

通过delete调用接口。这里会覆盖配置文件中配置的method属性。

    proxy.getNs("test").get("article").delete(1);
    // 发送请求 DELETE http://www.baidu.com/articles/1

put

通过put调用接口。这里会覆盖配置文件中配置的method属性。

    proxy.getNs("test").get("article").put(1,{
        data:{...}
    });
    // 发送请求 PUT http://www.baidu.com/articles/1

getPath

这个方法用于获取接口的路径,比如socket链接的地址等;

    proxy.getNs("test").get("article").getPath();
    // returns http://www.baidu.com/articles

6. Engines

继承自Compose类;提供接口的具体调用中间件。

proxy

调用接口的时候,会触发这个方法,返回一个Promise对象;

validate

调用接口的时候,会触发这个方法,返回一个Promise;

engine列表

  1. fetch

7. compose类

拷贝于koa的compose类;

use

添加一个中间件函数

    engine.use(async(ctx,next)=>{
        // do something

        await next();
    })

clear

清除掉所有的中间件方法

compose

生成执行方法,返回一个方法:(context: T, next: MiddleFunc) => Promise

callback

执行compose生成的方法,返回一个方法:() => Promise

errorHandle

错误处理方法

merge

合并多个compose的中间件

8. DEMO

可以贴到runkit中执行

let ModelProxy = require("modelproxy").ModelProxy;
let proxy = new ModelProxy();

proxy.loadConfig({
    "key": "test",
    "title": "p-uc",
    "engine": "default",
    "mockDir": "/mocks/",
    "states": {
        "prod": "http://www.baidu.com",
        "test": "http://www.baidu.com",
        "dev": "http://www.baidu.com",
        "stag": "http://www.baidu.com"
    },
    "state": "dev",
    "interfaces": [{
        "key": "article",
        "title": "文章接口",
        "method": "GET",
        "path": "/articles"
    }, {
        "key": "login",
        "title": "登陆接口",
        "method": "POST",
        "path": "/passport/login/:tag",
        "engine": "default",
        "config": {
            "test": "test-1"
        }
    }]
}, {});

let login = proxy.getNs("test").get("login");

if (login) {
    (async () => {
        console.log("登录接口:", login.getFullPath({ params: { tag: "ni", a: 33 } }), await login.get(null, {
            params: { tag: "test" }
        }));
    })();
}

let article = proxy.getNs("test").get("article");

if (article) {
    console.log("getPath", article.getFullPath({
        data: {},
        params: { a: 1 }
    }));
    (async () => {
        console.log(await article.get(null, { params: { tag: "nick" } }));
        console.log(await article.get(1, { params: { tag: "nick" } }));
        console.log(await article.put(1, { data: { tag: "nick" } }));
        console.log(await article.delete(1));
        console.log(await article.post({ data: { tag: "nick" } }));
        console.log(await proxy.execute("test", "article"));
        console.log(await proxy.execute("test", "login", {
            params: {
                tag: "nora"
            }
        }).catch(console.log));
    })()
}

if (login && article) {
    proxy.executeAll({
        login: login.get.bind(login, null, {
            params: {
                tag: "nora"
            }
        }),
        article: article.delete.bind(article, 1)
    }).then(console.log);

    proxy.race([{
        ns: login.ns, key: login.key, options: {
            params: { tag: "race" }
        }
    }, article.delete(1)]).then(console.log).catch(console.error);
}

9. ChangeList

  • 2.0.8
    • 添加了before,after,error中間件處理邏輯
  • 1.0.21
    • 修复了bug;
  • 1.0.20
    • 修复了bug;
  • 1.0.19
    • 修复了bug;
  • 1.0.18
    • 修复了bug;
  • 1.0.17
    • 修复了bug;
  • 1.0.16
    • 修复了bug;
  • 1.0.15
    • 修复了bug;
  • 1.0.14
    • 添加了mixin方法,修复了一些bug;
  • 1.0.11
    • 为compose类添加结束标志位;
  • 1.0.10
    • 修改Engine中的validate返回值为Promise;
  • 1.0.9
    • 添加了executeAll和race方法;

10. License

MIT

3.0.31

5 years ago

3.0.30

5 years ago

3.0.29

5 years ago

3.0.28

6 years ago

3.0.26

6 years ago

3.0.25

6 years ago

3.0.24

6 years ago

3.0.23

6 years ago

3.0.21

6 years ago

3.0.19

6 years ago

3.0.18

6 years ago

3.0.15

6 years ago

3.0.14

6 years ago

3.0.13

6 years ago

3.0.12

6 years ago

3.0.11

6 years ago

3.0.10

6 years ago

3.0.9

6 years ago

3.0.8

6 years ago

3.0.7

6 years ago

3.0.6

6 years ago

3.0.5

6 years ago

3.0.4

6 years ago

3.0.2

6 years ago

3.0.1

6 years ago

3.0.0

6 years ago

2.1.3

6 years ago

2.0.40

6 years ago

2.0.35

6 years ago

2.0.34

6 years ago

2.0.33

6 years ago

2.0.32

6 years ago

2.0.31

6 years ago

2.0.30

6 years ago

2.0.28

6 years ago

2.0.24

6 years ago

2.0.21

6 years ago

2.0.20

6 years ago

2.0.19

6 years ago

2.0.18

6 years ago

2.0.17

6 years ago

2.0.16

6 years ago

2.0.15

6 years ago

2.0.14

6 years ago

2.0.13

6 years ago

2.0.12

6 years ago

2.0.11

6 years ago

2.0.10

6 years ago

2.0.9

6 years ago

2.0.7

6 years ago

2.0.4

6 years ago

2.0.3

6 years ago

2.0.2

6 years ago

2.0.1

6 years ago

1.0.33

6 years ago

1.0.32

6 years ago

1.0.31

6 years ago

1.0.30

6 years ago

1.0.29

6 years ago

1.0.28

6 years ago

1.0.25

6 years ago

1.0.24

6 years ago

1.0.22

6 years ago

1.0.21

6 years ago

1.0.20

6 years ago

1.0.19

6 years ago

1.0.17

6 years ago

1.0.16

6 years ago

1.0.15

6 years ago

1.0.14

7 years ago

1.0.13

7 years ago

1.0.11

7 years ago

1.0.10

7 years ago

1.0.9

7 years ago

1.0.8

7 years ago

0.7.1

7 years ago

0.7.0

7 years ago

0.6.9

7 years ago

0.6.8

7 years ago

0.6.7

7 years ago

0.6.6

7 years ago

0.6.5

7 years ago

0.6.4

7 years ago

0.6.3

7 years ago

0.6.2

7 years ago

0.6.1

7 years ago

0.6.0

7 years ago

0.5.19

7 years ago

0.5.18

7 years ago

0.5.17

7 years ago

0.5.16

8 years ago

0.5.15

8 years ago

0.5.14

8 years ago

0.5.13

8 years ago

0.5.12

8 years ago

0.5.11

8 years ago

0.5.1

8 years ago

0.5.0

8 years ago

0.4.9

8 years ago

0.4.8

8 years ago

0.4.7

8 years ago

0.4.6

8 years ago

0.4.5

8 years ago

0.4.4

8 years ago

0.4.3

8 years ago

0.4.2

8 years ago

0.4.1

8 years ago

0.3.9

8 years ago

0.3.8

8 years ago

0.3.7

8 years ago

0.3.6

8 years ago

0.3.5

8 years ago

0.3.4

8 years ago

0.3.3

8 years ago

0.3.2

8 years ago

0.3.1

8 years ago

0.2.9

8 years ago

0.2.8

8 years ago

0.2.7

8 years ago

0.2.6

8 years ago

0.2.5

8 years ago

0.2.4

8 years ago

0.2.3

8 years ago

0.2.2

8 years ago

0.2.1

8 years ago

0.2.0

8 years ago

0.1.9

8 years ago

0.1.8

8 years ago

0.1.7

8 years ago

0.1.6

8 years ago

0.1.5

8 years ago

0.1.4

8 years ago

0.1.3

8 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago

0.0.9

8 years ago

0.0.8

8 years ago

1.0.7

8 years ago

1.0.6

8 years ago

1.0.5

8 years ago

1.0.4

8 years ago

1.0.3

8 years ago

1.0.2

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago