使用javascript 实现 ajax 访问 接口。

下面是w3c上面的例子,http://www.w3school.com.cn/ajax/ajax_database.asp。 被我稍微改装了两行。

问题一: 直接点击下面的字符串,都是可以访问的。“http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443 ”为什么用下面的写法访问不到?

问题二:应该怎么实现这个功能?图片描述

源码:

<html>
<head>


<script type="text/javascript">
function showCustomer(str)
{
var xmlhttp;    
if (str=="")
  {
  document.getElementById("txtHint").innerHTML="";
  return;
  }
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.onreadystatechange=function()
  {
  if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    alert(xmlhttp.responseText);// 弹出 返回的信息
    //document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
    }
  }
  xmlhttp.open("GET","http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443",false);//调用接口,根据电话号码获取 ,归属地信息
//xmlhttp.open("GET","/ajax/getcustomer.asp?q="+str,true);  http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443
xmlhttp.send();
}
</script>


</head>
<body>



<form action="" style="margin-top:15px;"> 
<label>请选择一位客户:
<select name="customers" onchange="showCustomer(this.value)" style="font-family:Verdana, Arial, Helvetica, sans-serif;">
<option value="APPLE">Apple Computer, Inc.</option>
<option value="BAIDU ">BAIDU, Inc</option>
<option value="Canon">Canon USA, Inc.</option>
<option value="Google">Google, Inc.</option>
<option value="Nokia">Nokia Corporation</option>
<option value="SONY">Sony Corporation of America</option>
</select>
</label>
</form>


<br />


<div id="txtHint">客户信息将在此处列出 ...</div>



</body>
</html>
阅读 16.8k
4 个回答

@xelz 说的很正确。访问不到是因为跨域问题,解决跨域的方案很多,jsonp 就是一种很有效的方式。

具体方法就是,创建 script 节点,再给该节点指定一个 src 属性,然后插入到 dom 中。(这是必须的,因为script必须被渲染,src 才会去异步加载,当脚本加载完毕之后,就回去执行提前定义好的方法)

更新:
@bumfod 说的对,当时随手一些,没有测试。我更新了一块代码!
以下代码不能运行,因为 mobile_tel_segment 不是去全局函数。以下代码没有测试过!

javascript(function(){
    var script = document.createElement('script');
    // 关注点 1
    script.src = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443?callback=mobile_tel_segment"
    document.querySelector("head").appendChild(script);

    // 关注店 2
    //var mobile_tel_segment = function(mobile_info){
    window.mobile_tel_segment = function(mobile_info){
        console.log(mobile_info);
        /* {
                mts:'1585078',
                province:'江苏',
                catName:'中国移动',
                telString:'15850781443',
                areaVid:'30511',
                ispVid:'3236139',
                carrier:'江苏移动'
            }
        */
    };
})();

注意 src 属性的值 http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443?callback=mobile_tel_segment

可以拷贝以下代码,我测试过。

html<!DOCTYPE html>
<html>
<head>
    <title>jsonp mobile query</title>
</head>
<body>
    <div id="result_panel" style="border: 1px solid #ccc; min-height: 100px; min-width: 200px;">

    </div>

    <input type="text" value="" id="mobile_number" placeholder="输入电话号码"><br />
    <button id="query_btn">查询按钮</button>

    <script type="text/javascript">
        (function(){
            // 封装的一个 jsonp 的工具
            var jsonp = (function(global){
                global.NAMWSPACE_CALLBACK = {}; // 命名空间

                var generate_jsonp_name = function(prefix){
                    // 在一个命名空间下动态创建一个函数
                    var func_name_suffix = Date.now() + '' +  Math.round(Math.random() * 10000);
                    var func_name = prefix + func_name_suffix;
                    return func_name;
                };

                var create_JSONP_factory = function(url){
                    var head = document.querySelector("head");
                    var script = document.createElement('script');
                    script.src = url;
                    // 开始渲染
                    head.appendChild(script);
                    return script;
                };

                var jsonp = function(url, options, callback){

                    if ( typeof options === 'function'  ) {
                        callback = options;
                        options = {};
                    }

                    var jsonp_callback_name = options.callback || 'callback';

                    var callback_func_name = generate_jsonp_name('jsonp_');

                    // 拼接 jsonp url
                    // 注意这里的拼接形式
                    // NAMWSPACE_CALLBACK.<register_function_name> 以供jsonp回调
                    var req_url = url + '&' + ( jsonp_callback_name + "=NAMWSPACE_CALLBACK." + callback_func_name);

                    // 创建并加载 jsonp
                    var script_node = create_JSONP_factory(req_url);

                    // 注册即将要被回调的函数
                    NAMWSPACE_CALLBACK[callback_func_name] = function(data){
                        // 回调
                        callback(data);
                        // 释放内存
                        // 删除节点
                        document.querySelector("head").removeChild(script_node);
                        // 删除改函数
                        delete NAMWSPACE_CALLBACK[callback_func_name];
                    };
                };
                return jsonp;
            })(window);


            // 业务逻辑代码
            document.querySelector("#query_btn").addEventListener('click', function(){

                var mobile_number = document.querySelector("#mobile_number").value;

                var url = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=" + mobile_number;
                // 调用 jsonp
                jsonp(url, function(data){
                    document.querySelector("#result_panel").innerHTML = JSON.stringify(data);
                    console.log(NAMWSPACE_CALLBACK);
                });
            });

        })();
    </script>
</body>
</html>

该 api 的 querystring 中有一个 callback 参数。(大多数jsonp的支持方式都是这种参数)

需要注意的是 jsonp 只能发送 GET 请求,这跟他的工作机制有关!

ajax是不能跨域的, 更明确一点来说,你在http://www.w3school.com.cn页面上只能请求http://www.w3school.com.cn这个域下的页面

=========================

回答评论中的补充提问:

上面的代码(ajax方式),一般情况下是无法跨域的, 这是浏览器的安全机制保障的,除非你要访问的网站声明了允许来自某些页面的ajax跨域请求(CORS,感谢评论指出), 这种方式浏览器的支持情况有限

常规的跨域方法,你可以搜索一下jsonp的相关资料,这个跟ajax是完全不同的实现原理,你想访问的链接 http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443 其实就是个jsonp类型的请求

一种简单的方式就是你在自己的后台通过http请求得到你想要的资源,然后前台通过ajax来访问你自己的后台方法

http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443
返回的数据你是否看到__GetZoneResult_ =
你是不是觉得这不像是一般的JSON数据?
是的。这的确不是,这是另外一种叫做JSONP
那么,如果说使用JavaScript创建一个脚本element

<script src="http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443"></script>

这样会有什么效果呢?那就是__GetZoneResult_这个变量变成了后面跟随的JSON数据了。
其实这样的做法非常常见。
//--------------------分隔线 例子1-----------------------------------
比如百度的搜索建议,http://suggestion.baidu.com/su?wd=wocao&from=superpage&json=1
如果把这段链接作为一个新脚本element的src 那么会有什么效果呢?
实际上是回调了window.baidu.sug这个函数 且第一个参数是随后的JSON数据
刚开始玩JavaScript的时候我看到这种数据我也懵了,之后看了看搜索引擎,突然觉得好机智
总之,这样跨域的URL一般情况下无法直接用AJAX获取。一般都会提供像JSONP这样的方式

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题