根据定义,Ajax是对服务器的异步请求。但这对于PHP文件中的变量意味着什么呢?
假设我们在for循环中有一个Ajax请求。每次迭代的请求都是相同的,除了输入略有不同(在本例中为someField
)。
for (var iOuter = 0; iOuter < 3; iOuter++) {
(function(i) {
myArrayVariable['someField'] = i;
$.ajax({
type: 'POST',
url: 'someurl.php',
data: myArrayVariable
})
.done(function() {
console.log("Finished " + i);
})
.fail(function(jqXHR, textStatus, error) {
console.error(error + ": " + textStatus);
});
})(iOuter);
}
在PHP中,我们可以这样写:
$val = $_POST['someField'];
$values = array();
for ($i = 0; $i < 10; $i++) {
push($values, ($val+$i));
}
我的问题是:因为这是一个异步请求,这是否意味着变量的范围在不同的请求之间共享?换句话说,$values
是否包含所有请求的所有值(当每个请求中的循环完成时),还是每个请求都是唯一的?
在扩展中,如何修改SESSION变量?我想这些应该是共享的吧?那么,如果我们将上面的代码片段替换为下面的代码,那么$values数组就会有所有的值吗?
$val = $_POST['someField'];
$_SESSION['values'] = array();
for ($i = 0; $i < 10; $i++) {
push($_SESSION['values'], ($val+$i));
}
或者有可能,因为一些小的时间差,即使第一个初始化的请求已经向数组中写入了一个值,第二个请求将会话变量重新初始化为空数组?所以价值可能会丢失?
总结一下:变量是在多个ajax请求中共享到同一个PHP文件,还是每个请求都是唯一的?那么SESSION变量和它们的初始化呢?当你在PHP中使用变量/函数时,如果你知道你在ajax请求中使用该文件,你应该注意什么时候?或者,一般来说:对同一文件的异步请求是否会相互影响?是在对同一PHP的多个ajax请求之间共享的变量文件,还是每个请求都是唯一的?
PHP变量在每次请求时都被重置,所以你不必担心一个请求会干扰另一个请求的值。
那么SESSION变量和它们的初始化呢?
$_SESSION
数据不同。它位于PHP进程之外的磁盘或内存中的某个位置,就像数据库数据一样。因此,像数据库一样,它可以在请求之间存活,无论是异步的还是其他方式,并且将按照先到先服务的原则进行修改。
在您的示例中,您在每个请求上设置$_SESSION['values'] = array();
,因此它将被重置为空数组。如果您刚刚向它推送了新值,那么来自先前请求的值将继续存在(至少在会话被销毁之前)。
关于会话的另一个要点:当会话处于活动状态时,PHP会锁定底层文件。因此,如果您的请求需要很长时间才能提供服务,并且同一会话的另一个请求进入,那么您将遇到麻烦。在这种情况下,最好的办法是在使用完会话文件后释放它,例如在脚本的早期。您总是可以在最后重新加载它以存储脚本的结果。
session_start();
... // do your session work early
session_write_close();
... // continue with your long script
对同一文件的异步请求是否会相互影响?
是的!如果处理需要很长时间处理文件,则另一个进程可能会出错。考虑这个脚本:
//allow script to run for a long time (or PHP might kill it)
set_time_limit(35);
$file = fopen("test.txt","w+"); //open file
flock($file,LOCK_EX); //set exclusive lock.
sleep(30); //sleep for 30 seconds
flock($file,LOCK_UN); //release lock
fclose($file);//close the file
如果另一个请求进来并试图在此进程休眠时打开此文件,您将遇到问题。
让我们运行一个测试,看看:
JS
for (ajax_var=1; ajax_var < 4; ajax_var++) {
$.ajax({
url: 'variable.php',
type: 'POST',
data: { 'ajax_var': ajax_var },
success: function(resp) {
console.log(resp);
}
});
}
PHP if(!isset($_SESSION)) { session_start(); }
$ajax_var = $_POST['ajax_var'];
$_SESSION['var'] = $ajax_var;
$data = [];
for ($php_var = 1; $php_var < 4; $php_var++) {
array_push($data, "Ajax Variable = " . $ajax_var);
array_push($data, "PHP Variable = " . $php_var);
array_push($data, "Session Variable = " . $_SESSION['var']);
array_push($data, " ");
}
print_r($data)
<<p> 控制台/strong> Array
(
[0] => Ajax Variable = 1
[1] => PHP Variable = 1
[2] => Session Variable = 1
[3] =>
[4] => Ajax Variable = 1
[5] => PHP Variable = 2
[6] => Session Variable = 1
[7] =>
[8] => Ajax Variable = 1
[9] => PHP Variable = 3
[10] => Session Variable = 1
[11] =>
)
variable_test_run.html:20
Array
(
[0] => Ajax Variable = 2
[1] => PHP Variable = 1
[2] => Session Variable = 2
[3] =>
[4] => Ajax Variable = 2
[5] => PHP Variable = 2
[6] => Session Variable = 2
[7] =>
[8] => Ajax Variable = 2
[9] => PHP Variable = 3
[10] => Session Variable = 2
[11] =>
)
variable_test_run.html:20
Array
(
[0] => Ajax Variable = 3
[1] => PHP Variable = 1
[2] => Session Variable = 3
[3] =>
[4] => Ajax Variable = 3
[5] => PHP Variable = 2
[6] => Session Variable = 3
[7] =>
[8] => Ajax Variable = 3
[9] => PHP Variable = 3
[10] => Session Variable = 3
[11] =>
)
看起来好像第一个php脚本在第二个php脚本启动之前就完成了。然而,我是在本地服务器上运行的,而实时服务器的响应速度可能比javascript代码稍慢。但是,两个脚本对齐并造成重叠的可能性几乎为零。我确信会话变量更有可能有重叠,但我从来没有真正理解为什么你需要在一个真实世界的例子中循环ajax调用。
每个请求都是唯一的。您可以使用会话,cookie,数据库来收集单独请求的数据。
会话将工作,因为每个ajax本质上与浏览器执行POST/GET并接收响应相同,除了它都发生在JS中。
php中的除了包含一个变量来标识它是AJAX之外,还可以检测它是否是AJAX(xmlhttprequest)。(似乎没有一个是完全防傻瓜的)。
更多信息在维基这里
关于ajax和普通请求的另一个软查询