美文网首页
JSONP跨域请求的小尝试

JSONP跨域请求的小尝试

作者: yandaxin | 来源:发表于2020-07-17 18:47 被阅读0次

    众所周知,为了安全性考虑浏览器是不支持跨域请求的,哪些请求是跨域请求?
    什么是跨域请求
    总之,同源是指 协议、域名、端口都相同,否则都算跨域。

    本文用JSONP的方式实现了一个小小的跨域请求demo,在<script>标签中请求另外一台服务器的脚本,回调函数拿到数据后渲染echart,蛮有意思。

    效果如图:


    test559是我的开发机

    //board.html
    获取到url传参date后,拼接为src链接地址,动态生成一个script标签
    <script src="https://test329.suanshubang.com/Stats.php?callback=callback&date=20200715"></script>
    跨域请求到test329上;
    向php脚本传递了两个参数,一个是callback回调函数,用于取回数据;另一个是date参数,是传递给脚本的入参。

    <!DOCTYPE html>
    <html>
    <head>
        <title>已分配任务的流转情况</title>
        <meta charset="utf-8">
        <script src="https://cdn.staticfile.org/echarts/4.7.0/echarts.min.js"></script>
    
        <div id="main" style="width: 900px;height:400px;"></div>
        <script>
            var g_data=[]
            function callback(data){
    
                console.log(data);
                g_data=data;
    
                var myChart = echarts.init(document.getElementById('main'));
    
                // 指定图表的配置项和数据
    
                option = {
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {            // 坐标轴指示器,坐标轴触发有效
                            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
                        }
                    },
                    legend: {
                        data: g_data.legend
                    },
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        containLabel: true
                    },
                    xAxis: [
                        {
                            type: 'category',
                            data: g_data.xAxis
                        }
                    ],
                    yAxis: [
                        {
                            type: 'value'
                        }
                    ],
                    series: g_data.series
                };
    
    
                // 使用刚指定的配置项和数据显示图表。
                myChart.setOption(option);
            }
    
        </script>
    
    
        <script language="javascript">
    
            function GetRequest() {
                var url = location.search; //获取url中"?"符后的字串
                var theRequest = new Object();
                if (url.indexOf("?") != -1) {
                    var str = url.substr(1);
                    strs = str.split("&");
                    for(var i = 0; i < strs.length; i ++) {
                        theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
                    }
                }
                return theRequest;
            }
    
            var req = GetRequest();
            var req1 = JSON.stringify(req.date);
    
            const script = document.createElement('script');
            script.src = "https://test329.suanshubang.com/Stats.php?callback=callback&date=" + req1;
            script.async = false;
            document.head.appendChild(script);
        </script>
    </head>
    </html>
    

    //Stats.php
    $date = $_GET['date']; 获取入参date;
    $params = $_GET['callback']; 获取回调函数;
    echo $params . '(' . json_encode($output) . ')'; 调用回调函数,即可将后端数据outout传递给前端。

    <?php
    
    $date = $_GET['date'];
    $date = substr($date, 1, 8);
    
    Bd_Init::init('assistantcheck');
    $stats  = new Stats();
    $output = $stats->execute(['date' => $date]);
    
    $params = $_GET['callback'];
    echo $params . '(' . json_encode($output) . ')';
    
    class Stats
    {
    
        private $objCheckTaskMain = null;
    
        public function __construct()
        {
            $this->objCheckTaskMain = new Service_Data_Task_CheckTaskMain();
        }
    
        public function execute($input)
        {
            $targetDate = isset($input['date']) && intval($input['date']) != 0 ? intval($input['date']) : date('Ymd', time());
            $zeroTime   = strtotime($targetDate);
    
            $sql = "select item,check_status,count(*) as cnt from tblCheckTaskMain where delete_time =0 and  dispatch_time >= " . $zeroTime . " group by item,check_status";
            $ret = $this->objCheckTaskMain->query($sql);
    
            $item_status_cnt = [];
            foreach ($ret as $agg_data) {
    
                $key = $agg_data['item'] . '-' . $agg_data['check_status'];
    
                $item_status_cnt[$key] = $agg_data['cnt'];
    
            }
    
            $check_status_set = array_unique(array_column($ret, 'check_status'));
            sort($check_status_set);
    
            $legend = [];
            foreach ($check_status_set as $check_status) {
                $legend[$check_status] = Conf_Config::CHECK_STATUS_MAP[$check_status];
            }
    
            $xAxis = [3 => '订正', 4 => '上镜', 5 => '微信单聊', 6 => '微信群聊', 7 => '兼职辅审', 8 => '兼职纯批'];
    
            $series = [];
    
            foreach ($legend as $check_status => $check_status_name) {
    
                $tmp = [
                    'name' => $check_status_name,
                    'type' => 'bar',
                    'data' => $this->getSeriesData($check_status, $xAxis, $item_status_cnt),
                ];
    
                $series[] = $tmp;
            }
    
            return [
                'legend' => array_values($legend),
                'xAxis'  => array_values($xAxis),
                'series' => array_values($series),
            ];
    
    
        }
    
    
        private function getSeriesData($check_status, $xAxis, $item_status_cnt)
        {
    
            $data = [];
            foreach ($xAxis as $item => $item_name) {
                $key    = $item . '-' . $check_status;
                $data[] = isset($item_status_cnt[$key]) ? intval($item_status_cnt[$key]) : 0;
            }
            return $data;
        }
    }
    

    过程中遇到的坑:
    document.createElement('script');是动态生成一个script标签,追加到html中,这个script会最后执行。导致echart拿不到后端数据,渲染失败。

    后来,将渲染echart的代码放到callback里函数执行,迎刃而解(前端小白两股瑟瑟)。

    鸣谢: https://blog.csdn.net/weixin_43837229/article/details/90720536

    相关文章

      网友评论

          本文标题:JSONP跨域请求的小尝试

          本文链接:https://www.haomeiwen.com/subject/hdcghktx.html