我有一个网站,它使用javascript和php逐帧生成gif。简而言之,该过程是:
- 使用 javascript 生成一个帧(存储为长 base64 编码字符串(
-
将此字符串发送到
writeToFile.php
,这将打开一个部分 copmlete 文件并将字符串添加到文件末尾。 - 等待成功写入文件,然后转到步骤 1 以获取下一帧
因此,最后,我将创建一个逐个文件,该文件按顺序包含 gif 的所有帧。大多数时候它有效。但是,有时,两个帧会切换,这会使 gif 卡顿(例如,当球击中此 gif 中的柱子时(。
我使用对 php 的调用将其拼凑在一起,并等待它们成功。根据我对 ajax 成功事件的理解,代码应该等到上一帧保存完毕后再生成下一帧,那么 php 怎么可能乱序写入文件呢?
我尝试在 ajax 请求中将异步设置为 false,但仍然会出现卡顿(尽管很少见(。最重要的是,生成速度较慢,因此这不是我理想的解决方案。
爪哇语
//Dostep - The first part of the frame generation. If we aren't done saving to file, wait 100 ms then check again
//This waits until the last frame is generated before generating a new one
var step=(function(){
var doStep = function () {
if (frameSavingToFile){ //Check
setTimeout(
function(){
doStep();
},
100 //if we are saving to file, wait
);
return;
}
//there is code here I've omitted which moves to the next frame, and stores the string
saveFrameToFile(frame);
}
return function () {
if (!stepping) setTimeout(doStep, 0);
};
}
function saveFrameToFile(theEncoder,isLastFrame){
frameSavingToFile=1;
var toAppend=window.btoa(theEncoder.stream().getData()); //add in the base 64 to the file
//save it to a file, on success set frameSavingToFile to 0
var toPassIn={'fileName':tmpFileName+".gif",'contents':toAppend};
$.ajax({
url: "php/writeToFile.php",
type: "POST",
data: toPassIn,
success: function(results) {
console.log(results);
frameSavingToFile=0;//we are no longer saving to file
if (isLastFrame){//this is set to 1 on the last frma
generationComplete();//don't generate more frames, load the gif for viewing
return;
}
}
});
}
PHP - 写入文件.php
打开文件,追加框架的内容,然后关闭
<?php
$data = $_POST['contents'];
$fileName = $_POST['fileName'];
$data = base64_decode($data);//puts it in a format I can store
$myfile = fopen('path/to/file/'.$fileName, "a") or die("Unable to open file!");
fwrite($myfile, $data);
fclose($myfile);
?>
代码过于复杂,有超时循环等等。为什么不简单地让 ajax 调用的成功处理程序重新调用以开始下一次写入?
例如
function savedata() {
var toAppend=window.btoa(theEncoder.stream().getData()); //add in the base 64 to the file
if (toAppend != '') { // or whatever it takes to see if the encoder's done
$.ajax(
blah blah blah,
success: savedata // keep "looping" until there's nothing left to do
);
} else {
console.log('done');
}
}
通过这种方式,您只需继续发出 ajax 请求,直到没有更多要保存的数据,一切都会"结束"。您还可以保证在上一个调用完成之前,下一个呼叫不会发出。您还将在每次调用中节省多达 ~99 毫秒的时间,而无需等待超时完成。
默认情况下,
jQuery 中的 ajax 调用是异步的。这意味着它们同时发送到服务器。尝试在$.ajax({})
配置对象中设置此标志:async: false
这会阻止 javascript 执行,直到请求从服务器返回。
你的代码不会等待,
- 等待成功写入文件,然后转到步骤 1 以获取下一帧
尝试使用同步请求:
$.ajax({
url: "php/writeToFile.php",
type: "POST",
async: false,
data: ...
jquery ajax :
异步(默认值:true( 类型:布尔值 默认情况下,发送所有请求 异步(即默认情况下设置为 true(。如果您需要 同步请求,将此选项设置为 false。跨域请求 和数据类型:"jsonp"请求不支持同步操作。 请注意,同步请求可能会暂时锁定浏览器, 在请求处于活动状态时禁用任何操作。