発火するたびに、新しいものを作成して前のものを置き換えるmocode()
ように見えます。<img />
同じものを再利用することで、よりスムーズな効果が得られます.srcを<img>
変更するだけです.
あなたのコードがどのように機能するのか正確にはわからないので、特定するのは難しいですが、次のようなものが必要だと思います:
function graphError() {
alert('Graph: reload failed');
}
var $graphImg = $("#GraphImage").on('error', graphError);
var tid = setInterval(mycode, 20000);
function mycode() {
var theDate = new Date();
var mili = theDate.getUTCDate() + theDate.toLocaleTimeString() + theDate.getMilliseconds();
$.ajax({
url: '@Url.Action("Chart", "Home", new {ForceNoCache = "theDate"})',
}).done(function(srcURL) {
$graphImg.attr('src', srcURL.replace("theDate", mili));
}).error(graphError);
}
URL を別の方法で作成する必要がある場合があります。少し考えれば、エラー メッセージをより具体的にすることができます。
編集
Tyco さん、あなたのソリューションは良さそうです。その間、私は同様のアイデアで遊んでいましたが、jQuery の Deferreds を中心とした劇的に異なるコードです。これらを使用したことがない場合は少し驚くかもしれませんが、非同期タスクがある場合は非常に便利です。
あなたの場合、グラフの URL をフェッチし、グラフの画像を読み込み、前のグラフをフェードアウトして新しいバージョンを表示するという 3 つの連続した非同期タスクがあります。
これをコーディングするのはかなり簡単ですが、コードはエラー トレラントである必要があります。特に、サーバーの応答 (URL と画像自体) が間違った順序で返されたり、setInterval
. Deferred は、前の反復で確立された関数チェーンをキャンセルする手段を提供することで、非常に役立ちます。
20 秒の間隔で問題はありませんが、ある日、インターネット/サーバーの動作が非常に遅くなるか、間隔を短くすることを決定する場合があります。
以前に Deferreds を使用したことがない限り、以下のコードは非常に異質に見えますが、私の側のエラーがなければ、機能するはずです。
Javascript:
$(function() {
var $graphImg1 = $("#GraphImage1");
var $graphImg2 = $("#GraphImage2");
var promises = {
fetchGraphUrl: null,
loadImg: null,
fadeOut: null
};
var graph_errors = {
threshold: 5,//set low for testing, higher in production environment.
count: 0
};
var interval = 5;//seconds
$graphImg2.on('error', function() {
if(promises.loadImg) {
promises.loadImg.reject();
}
}).on('load', function() {
if(promises.loadImg) {
promises.loadImg.resolve();
}
});
function graph_fetchURL(milli) {
if(promises.fetchGraph) {
promises.fetchGraph.reject(milli, 'fetchURL', 'timeout');
}
var dfrd = promises.fetchGraph = $.Deferred().fail(function() {
jqXHR.abort();
});
var jqXHR = $.ajax({
url: '@Url.Action("Chart", "Home", new {ForceNoCache = "theDate"})'
}).done(function(srcURL) {
dfrd.resolve(milli, srcURL);
}).fail(function(jqXHR, textStatus, errorThrown) {
dfrd.reject(milli, 'ajax', textStatus);
});
return dfrd.promise();
}
function graph_loadImg(milli, srcURL) {
if(promises.loadImg) {
promises.loadImg.reject(milli, 'loadImg', 'timeout');
}
//An extra deferred is needed here because $graphImg2's handlers don't know about milli.
var dfrd = $.Deferred();
promises.loadImg = $.Deferred().done(function() {
dfrd.resolve(milli);
}).fail(function() {
dfrd.reject(milli, 'loadGraph', 'load error');
});
$graphImg2.attr('src', srcURL.replace("theDate", milli));
return dfrd.promise();
}
function graph_fade(milli) {
if(promises.fadeOut) {
promises.fadeOut.reject(milli, 'fade', 'timeout');
}
promises.fadeOut = $.Deferred();
$graphImg2.show();
$graphImg1.fadeOut('fast', function() {
promises.fadeOut.resolve(milli);
});
return promises.fadeOut.promise();
}
function graph_swap() {
$graphImg1.attr('src', $graphImg2.attr('src')).show();
$graphImg2.hide();
}
function graph_error(timestamp, phase, txt) {
var txt = txt ? (' (' + txt + ')') : '';
console.log(timestamp + ': fetchGraph failed in the ' + phase + ' phase' + txt);
if(++graph_errors.count >= graph_errors.threshold) {
clearInterval(tid);
console.log('fetchGraph errors exceeded threshold (' + graph_errors.threshold + ')');
}
return $.Deferred().promise();//an unresolved, unrejected promise prevents the original promise propagating down the pipe.
}
function fetchGraph() {
var now = new Date();
var milli = now.getUTCDate() + now.toLocaleTimeString() + now.getMilliseconds();
graph_fetchURL(milli)
.pipe(graph_loadImg, graph_error)
.pipe(graph_fade, graph_error)
.pipe(graph_swap, graph_error);//this .pipe() chain is the glue that puts everything together.
}
fetchGraph();
var tid = setInterval(fetchGraph, interval * 1000);
});
CSS:
#graphWrapper {
position: relative;
float: left;
margin-right: 20px;
}
#GraphImage, #GraphImage2 {
position: absolute;
left: 0;
top: 0;
width: XXpx;
height: YYpx;
}
#GraphImage2 {
display: none;
}
HTML:
<div id="graphWrapper">
<img id="GraphImage1" alt="Graph of Results" src="" />
<img id="GraphImage2" alt="" src="" />
</div>
ご覧のとおり、すべてがかなり簡潔な関数の集まりに編成されており、それぞれが共通のテーマのバリエーションです。つまり:-
- 前の繰り返しからの同じ種類の未処理のタスクを拒否する
- 次の反復で拒否できる deferred を作成する
- タスク自体を実行する
- Deferred から派生した promise を返す
最後のタスクgraph_swap()
は簡単で、エラー ハンドラgraph_error()
は少し異なります。
詳細については、コード内のコメントを参照してください。
エラーの処理とサーバー応答の遅延に加えて、このアプローチの主な利点は、メインのイテレータ関数が非常にfetchGraph()
単純になることです。非常に巧妙な行はpipe()
、タスクを順序付けし、エラーをエラー ハンドラーにルーティングするチェーン コマンドのセットです。
私はこれをできる限りテストしましたが、あなた自身のソリューションのように、スムーズな移行ができると思います.