模拟服务端数据

在前面的章节中,我们设置了代理,于是所有的 HTTP 请求都可以先到达本地开发服务器,再被转发。在实际的开发中,后端的服务不一定马上可用,这就需要本地服务器另外一个能力:模拟数据(mock)。设置代理是 mock 的前提。

一个 ajax 请求发送到本地开发服务器后,我们可以设置:如果请求满足某个规则,则不转发这个请求,而是直接返回一个「假」结果给浏览器。在实际的开发中,我们常常先和服务端的同学商定 http 请求的接口接受什么参数,返回什么结果,然后先用 mock 数据来模拟,自己和自己「联调」。等待服务端同学开发好了,再解除 mock,用真实数据「联调」。

模拟正常返回数据

设置模拟数据时需要在工程根目录下的 mock 子目录中的建立文件。首先在工程中增加 mock 目录,并在其中创建文件 puzzlecards.js(取其他名字也可以,名字这里不需要)。如果想 mock 掉我们在上一个章节中的向 /dev/random_joke 的 ajax 调用,需要写入以下内容到文件,

const random_jokes = [
  {
    setup: 'What is the object oriented way to get wealthy ?',
      punchline: 'Inheritance',
  },
  {
    setup: 'To understand what recursion is...',
    punchline: "You must first understand what recursion is",
  },
  {
    setup: 'What do you call a factory that sells passable products?',
    punchline: 'A satisfactory',
  },
];

let random_joke_call_count = 0;

export default {
  'get /dev/random_joke': function (req, res) {
    const responseObj = random_jokes[random_joke_call_count % random_jokes.length];
    random_joke_call_count += 1;
    setTimeout(() => {
      res.json(responseObj);
    }, 3000);
  },
};

如果你不断地刷新页面,会发现每次拿到的数据是不同的。并且由于 setTimeout 的存在使得卡片的更新变慢了。

image.png | left | 747x183

我们通过这个例子解释一下怎么写 mock 数据。

首先,整个文件需要 export 出一个 js 对象。对象的 key 是由

<Http_verb> <Resource_uri>

构成的,值是 function,当一个 ajax 调用匹配了 key 后,与之对应的 function 就会被执行。函数中我们调用 res.json 就可以给浏览器返回结果。函数中可以使用 setTimeout 来模拟异步调用服务时的时延。

模拟出错

利用 res.status 也可以模拟 http 请求出错。例如,我们把文件中的 export default 块替换成下面的内容,

export default {
  'get /dev/random_joke': function (req, res) {
    res.status(500);
    res.json({});
  },
};

在 dva model 中我们加入简单的错误捕获:

import { message } from 'antd';

// ... 原有逻辑不修改

  try { // 加入 try catch 捕获抛错
    const puzzle = yield call(request, endPointURI);
    yield put({ type: 'addNewCard', payload: puzzle });

    yield call(delay, 3000);

    const puzzle2 = yield call(request, endPointURI);
    yield put({ type: 'addNewCard', payload: puzzle2 });
  } catch (e) {
    message.error('数据获取失败'); // 打印错误信息
  }

于是可以看到出错状况下的页面:

image.png | left | 747x224

在每一个调用点做打印错误信息很麻烦,这里只是为了展示 mock 出错场景。在实际的开发中,一般会统一处理 http 请求错误时的信息提示。

简单数据模拟

刚才的模拟中,mock 具备动态改变、延时返回等能力,如果你不需要这个能力,也可以简单地使用对象。

export default {
  'get /dev/random_joke': {
    setup: 'What is the object oriented way to get wealthy ?',
    punchline: 'Inheritance',
  },
};