Skip to content

取消 mock

接口二像性

前面已经介绍到过在awe-axios的世界里,接口既是真实接口,又是mock接口,就像波粒二象性那样,接口也呈现二像性。
并且在之前的章节中,我们学会了如何通过配置将真实接口变为mock接口,现在将会讲解如何将mock接口变为真实接口。awe-axios提供了类方法来取消mock接口,如下所示:

关于取消mock接口

这里说的取消mock接口是从逻辑上进行取消,也就是说同样的调用方式不会走mock接口,而是走真实接口。这样设计的目的在于,使得代码满足开闭原则,即可以通过配置来切换接口的使用方式,而不需要修改代码。

信号量机制

awe-axios借鉴了axios的信号量机制,在awe-axios中,我们也可以通过配置信号量来逻辑取消mock,如下所示:

ts
// 创建mock控制器
const mockCtr = new SignalController();
@HttpApi('http://localhost:3000/users/')
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      signal: mockCtr.signal,
      handlers: async ({ request, params }) => {
        const { page, size } = params;
        // 1,10
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 发送到mock接口 :http://localhost:3000/users/176189724290824/default/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();
// 取消mock(走真实的接口)
mockCtr.abort();
// 发送到服务器真实接口 : http://localhost:3000/users/pages/1/20
let { data: data2 } = await userApi.getUserPages(1, 20)();

上面的案例中,我们通过mockCtr.signal配置了信号量,当mockCtr.abort()被调用时,awe-axios会取消mock接口的调用,从而走真实接口。
⭐所以当后端接口开发完毕时你没有必要将其改为userApi.getUserPages(1, 20)方式

设置 mock 接口使用次数

除了使用信号量来取消mock接口,awe-axios还提供了mock次数配置,也就是说在mock接口被调用的次数达到指定次数后就会自动取消,而后全部走真实接口,这有什么好处呢?我们可以在页面初次加载的时候调用mock接口,先展示部分假数据,等到数据加载完成后再调用真实接口,这样可以提升用户体验。

如下所示:

ts
@HttpApi('http://localhost:3000/users/')
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      count: 3,
      handlers: async ({ request, params }) => {
        console.log('mock接口');
        console.log(request.url);
        const { page, size } = params;
        // 1,10
        console.log(page, size);
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 发送到mock接口 :http://localhost:3000/users/176189724290824/default/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();
// 发送到mock接口 :http://localhost:3000/users/176189724290824/default/pages/1/20
let { data: data2 } = await userApi.getUserPages(1, 20)();
// 发送到mock接口 :http://localhost:3000/users/176189724290824/default/pages/1/30
let { data: data3 } = await userApi.getUserPages(1, 30)();
// mock接口次数达到上限,走真实的接口
// 发送到服务器真实接口 : http://localhost:3000/users/pages/1/40
let { data: data4 } = await userApi.getUserPages(1, 40)();
// 发送到服务器真实接口 : http://localhost:3000/users/pages/1/50
let { data: data5 } = await userApi.getUserPages(1, 50)();
// 发送到服务器真实接口 : http://localhost:3000/users/pages/1/60
let { data: data6 } = await userApi.getUserPages(1, 60)();

mock 开关

试想一下有这种场景:前后端联调时,我们需要在后端接口开发完毕前,前端先使用mock接口的假数据,而后端接口开发完毕后,我们再将mock接口关闭,这样就可以看到真实接口的数据。这时候我们就可以通过配置mock开关来实现这个功能,awe-axios支持三种级别的mock开关配置,分别是接口级别、类级别、全局级别,优先级从高到低,如下所示:

接口级别开启/关闭

我们可以通过mock配置项中的on属性来控制接口是否使用mock接口,这样可以一个后端接口开发完毕后关闭一个mock接口,实现方法级别的控制,这个优先级最高,如下所示:

ts
@HttpApi('http://localhost:3000/users/')
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      on: false,
      handlers: async ({ request, params }) => {
        // 1,10
        const { page, size } = params;
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 由于关闭了mock,所以走真实的接口 : http://localhost:3000/users/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();

默认值

当你配置mock接口时,即便没有配置on属性其默认也为true,也就是说如果你要关闭mock接口,你需要显式的配置on: false

类级别开启/关闭

除了接口级别的开关,awe-axios还提供了类级别的开关,也就是说你可以在整个类中控制是否使用mock接口,这样你就能按模块(类)来统一控制多个mock接口的开关,这个的优先级小于接口级别的开关但高于全局级别的开关。如下所示:

ts
@HttpApi({
  baseURL: 'http://localhost:3000/users/',
  mock: {
    on: false,
  },
})
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      handlers: async ({ request, params }) => {
        // 1,10
        const { page, size } = params;
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 由于关闭了mock,所以走真实的接口 : http://localhost:3000/users/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();

全局开启/关闭

在前面的介绍中已经提到过全局打开mock接口。即MockAPI.on(),但是这个优先级最低。如下所示:

ts
test.only('mock开关', async () => {
  MockAPI.off();
  @HttpApi('http://localhost:3000/users/')
  class UserApi {
    @Get({
      url: '/pages/:page/:size',
      mock: {
        handlers: async ({ request, params }) => {
          // 1,10
          const { page, size } = params;
          return HttpResponse.json({
            data: [
              { id: 1, name: 'Alice' },
              { id: 2, name: 'Bob' },
            ],
          });
        },
      },
    })
    getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
  }
  let userApi = new UserApi();
  // 由于关闭了mock,所以走真实的接口 : http://localhost:3000/users/pages/1/10
  let { data: data1 } = await userApi.getUserPages(1, 10)();

环境设置

mock开关虽然能够显示的控制mock接口的开放和关闭,但是在实际开发中,我们可能需要工具能够智能的根据不同的环境来控制mock接口的使用,比如开发环境使用mock接口,测试/生产环境使用真实接口。awe-axios提供了环境设置的功能,我们通过设置环境控制mock接口和真实接口的切换,也就是说即便你打开了mock接口,但是环境不满足mock环境也不会走mock接口而是真实接口。awe-axios提供了三种级别的环境设置方式,分别是接口级别、类级别、全局级别,优先级从高到低,如下所示:

接口级别环境感知

通过condition配置项即可实现接口级别的环境感知,如下所示:

ts
@HttpApi('http://localhost:3000/users/')
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      condition: () => {
        // 测试环境下走mock接口
        return process.env.NODE_ENV === 'test';
      },
      handlers: async ({ request, params }) => {
        // 1,10
        const { page, size } = params;
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 由于是测试环境,所以走mock接口 : http://localhost:3000/users/176189724290824/default/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();

类级别环境感知

类级别的环境设置优先级比接口级别低,但是比全局级别高,如下所示:

ts
@HttpApi({
  baseURL: 'http://localhost:3000/users/',
  mock: {
    condition: () => {
      // 测试环境下走mock接口
      return process.env.NODE_ENV === 'test';
    },
  },
})
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      handlers: async ({ request, params }) => {
        // 1,10
        const { page, size } = params;
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 由于关闭了mock,所以走真实的接口 : http://localhost:3000/users/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();

全局环境感知

全局环境设置优先级最低,如下所示:

ts
MockAPI.setCondition(() => {
  return process.env.NODE_ENV === 'test';
});
@HttpApi({
  baseURL: 'http://localhost:3000/users/',
})
class UserApi {
  @Get({
    url: '/pages/:page/:size',
    mock: {
      handlers: async ({ request, params }) => {
        // 1,10
        const { page, size } = params;
        return HttpResponse.json({
          data: [
            { id: 1, name: 'Alice' },
            { id: 2, name: 'Bob' },
          ],
        });
      },
    },
  })
  getUserPages(@PathParam('page') page: number, @PathParam('size') size: number): any {}
}
let userApi = new UserApi();
// 由于关闭了mock,所以走真实的接口 : http://localhost:3000/users/pages/1/10
let { data: data1 } = await userApi.getUserPages(1, 10)();

默认值

实际上你没有必要全局再设置process.env.NODE_ENV === 'test',因为awe-axios默认设置全局process.env.NODE_ENV === 'test'