Skip to content

Commit e025f9a

Browse files
committed
JSONP一节翻译完毕
1 parent d02e4cb commit e025f9a

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

chapter8.markdown

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,4 +438,106 @@ getdata.php可以是任何类型的页面或者脚本。callback参数指定用
438438

439439
(译注:原文这里说得不是太明白。JSONP的返回内容如上面的代码片段,它的工作原理是在页面中动态插入一个脚本,这个脚本的内容是函数调用+JSON数据,其中要调用的函数是在页面中已经定义好的,数据以参数的形式存在。一般情况下数据由服务端动态生成,而函数由页面生成,为了使返回的脚本能调用到正确的函数,在请求的时候一般会带上callback参数以便后台动态返回处理函数的名字。)
440440

441+
#### JSONP示例:井字棋
442+
443+
我们来看一个使用JSONP的井字棋游戏示例,玩家就是客户端(浏览器)和服务器。它们两者都会产生1到9之间的随机数,我们使用JSONP去取服务器产生的数字(图8-2)。
444+
445+
你可以在<http://jspatterns.com/book/8/ttt.html>玩这个游戏。
446+
447+
![图8-2 使用JSONP的井字棋游戏](./figure/chapter8/8-2.jpg)
448+
449+
图8-2 使用JSONP的井字棋游戏
450+
451+
界面上有两个按钮:一个用于开始新游戏,一个用于取服务器下的棋(客户端下的棋会在一定数量的延时之后自动进行):
452+
453+
<button id="new">New game</button>
454+
<button id="server">Server play</button>
455+
456+
界面上包含9个单元格,每个都有对应的id,比如:
457+
458+
<td id="cell-1">&nbsp;</td>
459+
<td id="cell-2">&nbsp;</td>
460+
<td id="cell-3">&nbsp;</td>
461+
...
462+
463+
整个游戏是在一个全局对象ttt中实现:
464+
465+
var ttt = {

466+
// cells played so far
467+
played: [],
468+
469+
// shorthand

470+
get: function (id) {
471+
return document.getElementById(id);
472+
},
473+
474+
// handle clicks
475+
setup: function () {
476+
this.get('new').onclick = this.newGame;
477+
this.get('server').onclick = this.remoteRequest;
478+
},
479+
480+
// clean the board
481+
newGame: function () {
482+
var tds = document.getElementsByTagName("td"),
483+
max = tds.length,

484+
i;
485+
for (i = 0; i < max; i += 1) {
486+
tds[i].innerHTML = "&nbsp;";
487+
}
488+
ttt.played = [];
489+
},
490+
491+
// make a request
492+
remoteRequest: function () {
493+
var script = document.createElement("script");
494+
script.src = "server.php?callback=ttt.serverPlay&played=" + ttt.played.join(',');
495+
document.body.appendChild(script);
496+
},
497+
498+
// callback, server's turn to play
499+
serverPlay: function (data) {
500+
if (data.error) {
501+
alert(data.error);
502+
return;
503+
}
504+
505+
data = parseInt(data, 10);
506+
this.played.push(data);
507+
508+
this.get('cell-' + data).innerHTML = '<span class="server">X<\/span>';
509+
510+
setTimeout(function () {
511+
ttt.clientPlay();
512+
}, 300); // as if thinking hard
513+
},
514+
515+
// client's turn to play
516+
clientPlay: function () {
517+
var data = 5;
518+
519+
if (this.played.length === 9) {
520+
alert("Game over");
521+
return;
522+
}
523+
524+
// keep coming up with random numbers 1-9

525+
// until one not taken cell is found

526+
while (this.get('cell-' + data).innerHTML !== "&nbsp;") {
527+
data = Math.ceil(Math.random() * 9); }
528+
this.get('cell-' + data).innerHTML = 'O';
529+
this.played.push(data);
530+
}
531+
};
532+
533+
ttt对象维护着一个已经填过的单元格的列表ttt.played,并且将它发送给服务器,这样服务器就可以返回一个没有玩过的数字。如果有错误发生,服务器会像这样响应:
534+
535+
ttt.serverPlay({"error": "Error description here"});
536+
537+
如你所见,JSONP中的回调函数必须是公开的并且全局可访问的函数,它并不一定要是全局函数,也可以是一个全局对象的方法。如果没有错误发生,服务器将会返回一个函数调用,像这样:
538+
539+
ttt.serverPlay(3);
540+
541+
这里的3是指3号单元格是服务器要下棋的位置。在这种情况下,数据非常简单,甚至都不需要使用JSON格式,只需要一个简单的值就可以了。
542+
441543

0 commit comments

Comments
 (0)