文章目录

每天都得找点乐子,今天的乐子就是“WEB开发中前端与后端通信的解决办法”。

首先,说一下“神圣”的需求。假设,我们面前是一个报名活动的页面。所有的逻辑都发生在这报名按钮上,下面是导图:

报名按钮导图 - 胡旭个人博客


做法一


按钮是一个链接,当我们用可爱的手指轻轻抚摸他时。他会告诉浏览器,我是一个链接。之后,浏览器被跳转到一个新的连接上。与此同时,后端会执行当前的逻辑,渲染对应的WEB页面。

这种做法很糟糕:

1、用户体验不好,跳转页面的吞吐量比较高,加大用户的等待时间

2、同时,也加大服务器的负担;

3、代码冗余度较高,需要写若干个前端页面和后端方法。

做法二


那么,用 AJAX 来实现前后端的通信(异步)也许是个不错的做法。既然,谈到通信,那么必定要有个标准。那,标准是个什么东西?

举个例子(秒懂!哈哈)

5E2EF8CB-6607-41E6-9B25-CB164FC2A2AB

公认的标准脸型:  

不符合标准的脸型:

如花



所以,你知道。如果程序没有标准,是一件多么令人“恼怒”的事情。

需要两个 PHP 类库:

标准接口:

<?php
namespace Common\Library\Int;
/**
 * For communicating each other.
 *
 * @author genialx
 * @see ErrorMsg
 */
interface ErrorMsgInterface
{
    //============//
    /* Error code */
    //============//

    /**
     * Success.
     *
     * @author genialx
     */
    const ERROR_CODE_0X0001 = 0x0001; // success.

    /**
     * unknown error.
     *
     * @author genialx
     */
    const ERROR_CODE_0X0002 = 0x0002;

    /* Error type */
    const ERROR_TYPE_JSON = 'json'; // for json format
}

实现类库:

<?php
namespace Common\Library\Util;
use Common\Library\Int\ErrorMsgInterface;
/**
 * For returning the message in json.
 *
 * It must implement the interface to communicate each other.
 *
 * @author genialx
 *
 */
class ErrorMsg implements ErrorMsgInterface {
    private $_errCode = '';
    private $_errMsg = '';
    private $_type = 'json';
    private $_return = '';
    private $_data = array();
    /**
     * __call method.
     *
     * @author genialx
     * @param string $methodName
     * @param string $args
     */
    Public function __call($methodName, $args) {
        $this->_data[$methodName] = $args[0];
        return $this;
    }
    /**
     * Set the type.
     *
     * @author genialx
     * @param unknown $type
     */
    public function setType($type = self::ERROR_TYPE_JSON) {
        $this->_type = $type;
    }
    /**
     * Get the type.
     *
     * @author genialx
     * @return string
     */
    public function getType() {
        return $this->_type;
    }
    public function setErrCode($errCode) {
        $this->_errCode = $errCode;
        $this->_setMsg($errCode);
    }
    /**
     * Get the errCode.
     *
     * @author genialx
     * @return string
     */
    public function getErrCode() {
        return $this->_errCode;
    }
    /**
     * Get set tht errMsg.
     *
     * @author genialx
     * @param unknown $errMsg
     */
    public function setErrMsg($errMsg) {
        $this->_errMsg = $errMsg;
    }
    /**
     * Get the errMsg.
     *
     * @author genialx
     * @return string
     */
    public function getErrMsg() {
        return $this->_errMsg;
    }
    /**
     * Get the return.
     *
     * @author genialx
     * @return string
     */
    public function getReturn() {
        if ($this->_errCode == '') return $this->_getUnknowReturn();
        switch ($this->_type) {
            case self::ERROR_TYPE_JSON:
                return $this->_getJSON();;
            break;
            default:
                return $this->_getUnknowReturn();
            break;
        }
    }
    /**
     * Get the return in the json format, according to the private vars.
     *
     * @return string
     */
    private function _getJSON() {
        $json = array('errCode' => $this->getErrCode(), 'errMsg' => $this->getErrMsg());
        if (count($this->_data)) {
            $json = array_merge($json, $this->_data);
        }
        return json_encode($json);
    }
    /**
     * Get the message according to the error code.
     *
     * @author genailx
     */
    private function _setMsg($errCode = null) {
        if (!isset($errCode)) {
            $errCode = $this->_errCode;
        }
        if ($this->_errMsg != '') return false;
        switch ($errCode) {
            case self::ERROR_CODE_0X0001:
                $this->setErrMsg('Success.');
            break;
            case self::ERROR_CODE_0X0002:
                $this->setErrMsg('Unknown error.');
            break;
            default:
                $this->setErrMsg('Uknown error.');
            break;
        }
    }
    /**
     * Get the unknown return in json format.
     *
     * @author genailx
     * @return string
     */
    private function _getUnknowReturn() {
        $json = array("errCode" => self::ERROR_CODE_0X0002, "errMsg" => "Unknown error.");
        return json_encode($json);
    }
    /**
     * Get the return of the success case.
     *
     * @author genailx
     * @return string
     */
    public function getSuccessReturn() {
        $this->_errCode = self::ERROR_CODE_0X0001;
        return $this->getReturn();
    }
}

后端:

<?php
namespace API\Controller;
use Common\Library\Util\ErrorMsg;

class Web extends Controller
{
    /**
     * 参加活动.
     *
     */
    public function addActivity()
    {
        /* 初始化局部变量 */
        $EM = new ErrorMsg();
        // check 
        if (true) {
            $EM->setErrCode($EM::ERROR_CODE_0X0001);
            $EM->setType($EM::ERROR_TYPE_JSON);
            $EM->setErrMsg("successful message to show.");
            $EM->getReturn();
            return true;
        } else {
            $EM->setErrCode($EM::ERROR_CODE_0X0002);
            $EM->setType($EM::ERROR_TYPE_JSON);
            $EM->setErrMsg("failed message to show.");
            $EM->getReturn();
            return false;
        }
    }
}

前端 HTML:

<script type="text/javascript" src="add-activity.js"></script>
<script>
$(function () {
    homeUrl = "__HOME_URL__";
    addActivit.init(); // 初始化操作
});
</script>

前端Javascript:

var _homeUrl = '';

var addActivity = {

  // 注册事件
  var triggerEvents = function() {
      $("#add-button").on("touchstart", function() {
          var parameters = $("#parameters").val();
          $.get(_homeUrl + "/API/Web/addActivity?parameters=" + parameters, function(result) {
              var json = $.parseJSON(result); // 解析来自后台的json字符串
              // 根据返回码,执行相应动作
              switch(json.errCode) {
                  case 0x0001:
                  // some statements...
                  break;
                  case 0x0002:
                  // some statements...
                  break;
                  default:
                  // some statements...
                  break;
              }
          });
      });
  };

  return {
    init: function(homeUrl) {
      _homeUrl = homeUrl;
      triggerEvents(); //注册事件
    };
  };
}();

完善


当然,这个模式可以根据不同项目做少许改变。

目前,也许会遇到这样的问题。当逻辑比较复杂时,那么注册在这个”加入“按钮上的事件函数的处理逻辑会涉及多次请求服务器来判断当前的状态(是或否)。这种情况,对于编码和用户体验(延时等待)都不是好的。所以,其实也可以在报名页面渲染时,把必要的字段放在 input[type=’hidden’] 中。这样,也就页面了JS多次请求服务器的问题。

注:该文章代码均为伪代码,不可直接复用。文中 PHP 类库样例代码基于 ThinkPHP 框架。

Share:

2 comments

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.