模块5之实现前端页面对秒杀结果的轮询

简介

  当秒杀请求被放入queue中后,由于MySQL处理能力有限,可能需要等待一段时间才能完成对秒杀请求的处理;这段时间前端会不断询问秒杀请求的处理结果。

1.在前端定义轮询函数。

  每隔50ms,调用“/miaosha/getresult”接口,传入参数goodsId,当秒杀成功时提示是否查看订单页面,当秒杀失败是显示失败信息,当秒杀请求

仍在处理中时,等待50ms后再次查询。

 1 //轮询功能:每隔50ms,查看一次是否秒杀成功
 2     function getResult(goodsId) {
 3         g_showLoading();
 4         $.ajax({
 5             url:"/miaosha/getresult",
 6             type:"GET",
 7             data:{
 8                 goodsId:$("#goodsId").val(),
 9             },
10             success:function (data){
11                 var result = data.data;
12                 if (result<0){
13                     layer.msg("对不起,秒杀失败");
14                 }else if (result==0){
15                     setTimeout(function () {
16                         getResult(goodsId);
17                     },50)
18                 } else {
19                     layer.confirm("恭喜你,秒杀成功。查看订单?",{btn:["确定","取消"]},
20                                     function () {
21                                         window.location.href="/order_detail.htm?orderId="+result;
22                                     },
23                                     function () {
24                                         layer.closeAll();
25 
26                                     });
27                 }
28 
29             },
30             error:function () {
31                 layer.msg(data.msg);
32             }
33         });
34 
35     }

2.后端getResult方法会返回秒杀的处理结果

  成功:返回订单id;失败:返回-1,表示没有库存了;正在处理中:返回0。

  

 1 /*
 2     * 轮询功能:查看秒杀的结果
 3     * */
 4     @AccessLimit(seconds = 5,maxCount = 5)
 5     @RequestMapping(value = "/getresult",method = RequestMethod.GET)
 6     @ResponseBody
 7     public Result<Long> getResult(Model model,MiaoshaUser user,@RequestParam("goodsId")long goodsId) {
 8         //判断现在的秒杀状态
 9         long result = miaoshaService.getMiaoshaResult(user.getId(),goodsId);
10 11         return Result.success(result);
12     }

3.miaoshaService.java中的getMiaoshaResult()方法才是真正获取秒杀结果的方法

  该方法的参数有两个,goodsId,userId。此两个参数将被用来查询使用。

  在该方法中进行两次判断,第一次,goodsId+userId相对应的秒杀订单是否存在,存在返回订单号;不存在,进行第二次

  第二次,判断减库存的情况,减库存失败就返回秒杀失败,其它的情况就认为正在处理中。

 1 //轮询中判断秒杀的状态
 2     public long getMiaoshaResult(Long userId, long goodsId) {
 3         //1.判断秒杀是否成功
 4         OrderInfo orderInfo = orderInfoService.getByUserIdGoodsId(userId,goodsId);
 5         if (orderInfo != null) {
 6             return orderInfo.getId();                                                                                   //秒杀成功返回订单id
 7         }
 8         //2.如果不成功,判断是否秒杀失败或秒杀进行中
 9         if (!getReduceResult(goodsId)) {
10             return -1;        //没有库存,秒杀失败
11         }else return 0;       //有库存,正在秒杀
12     }

  在第二次判断中,需要使用getResult()函数,此函数为获取减库存结果的函数,并且还有一个与之对应的setResult()函数用来保存减库存结果。

 

1 private void setReduceResult(long goodsId, boolean reduceResult) {
2         redisService.set(ReduceResultPrefix.getReduceResult,""+goodsId,reduceResult);
3     }
4 
5     private boolean getReduceResult(long goodsId) {
6         return  redisService.exists(ReduceResultPrefix.getReduceResult,""+goodsId);
7     }

  在减库存的操作过后调用setReduceResult方法,将减库存的结果,缓存到redis中。

 1 //三步走:减库存,下订单,写入秒杀订单
 2     @Transactional
 3     public OrderInfo miaoSha(long useId, long goodsId) {
 4                                                                                                                         //减库存,并设置减库存的结果
 5         boolean reduceResult=miaoshaGoodsService.reduceStock(goodsId);
 6         miaoshaGoodsService.reduceFMStock(goodsId);
 7         setReduceResult(goodsId,reduceResult);
 8         if (!reduceResult) {
 9             return null;
10         }

  其中miaoshaGoodsService.reduceStock(goodsId);会调用ORM框架的update操作去减库存;

  而update操作会返回影响的行数,如果返回值为1,代表减库存成功;返回值为0,代表减库存失败。

  在miaoshaGoodsService.reduceStock()方法中会将0,1转化为false,true作为返回值,然后赋值给reduceResult变量。

  然后将reduceResult变量缓存入redis中。

 

posted on 2020-04-13 20:46  hello,bdiskl  阅读(1310)  评论(0编辑  收藏  举报

导航