以下の ajax コードがあり、正常に動作しています。
$.ajax({
//async: false,
url: "/Tests/GetData/",
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (data) {
$.each(data, function (i, item) {
$.ajax({
//async: false,
url: "/Tests/DoTask/",
type: 'POST',
data: { taskName: item.TaskName },
success: function () {
$("#Status").append('Task PASSED.<br/>');
},
error: function () {
$("#Status").append('Task FAILED!<br/>');
},
beforeSend: function () {
$("#Status").append('Doing task...<br/>');
}
});
});
$("#Status").append('Process completed.</span><br/>');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
$("#Status").append('Error: ' + errorThrown + '<br/>');
},
beforeSend: function () {
$("#Status").append('<br/>Process started.<br/>');
}
});
これの問題は、非同期であるため、ビュー コントロールのメッセージが順不同で表示されることです。そのため、ajax 内にオプション async:false を配置することにしましたが、これにより、メッセージが順序どおりに表示されているにもかかわらず、Web アプリケーションが完全にブロックされます...悪い考えなので、ajax 呼び出しを処理するキューを実装し、オプション async:false を使用しないことを考えました。私はグーグルで検索し、これを見つけました:
jQuery deferred はどのように使用できますか?
上記ページのコードの下:
/* Class: Buffer
* methods: append
*
* Constructor: takes a function which will be the task handler to be called
*
* .append appends a task to the buffer. Buffer will only call a task when the
* previous task has finished
*/
var Buffer = function(handler) {
var tasks = [];
// empty resolved deferred object
var deferred = $.when();
// handle the next object
function handleNextTask() {
// if the current deferred task has resolved and there are more tasks
if (deferred.isResolved() && tasks.length > 0) {
// grab a task
var task = tasks.shift();
// set the deferred to be deferred returned from the handler
deferred = handler(task);
// if its not a deferred object then set it to be an empty deferred object
if (!(deferred && deferred.promise)) {
deferred = $.when();
}
// if we have tasks left then handle the next one when the current one
// is done.
if (tasks.length > 0) {
deferred.done(handleNextTask);
}
}
}
// appends a task.
this.append = function(task) {
// add to the array
tasks.push(task);
// handle the next task
handleNextTask();
};
};
有望に思えたので、試してみることにしました。そのため、ajax コードを変更し、結果の下で、内側の ajax ブロックを置き換えたことに注意してください。
$.ajax({
//async: false,
url: "/Tests/GetData/",
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function (data) {
$.each(data, function (i, item) {
Buffer({
//async: false,
url: "/Tests/DoTask/",
type: 'POST',
data: { taskName: item.TaskName },
success: function () {
$("#Status").append('Task done.<br/>');
},
error: function () {
$("#Status").append('Task failed!<br/>');
},
beforeSend: function () {
$("#Status").append('Doing task...<br/>');
}
});
});
$("#Status").append('Process completed.</span><br/>');
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
$("#Status").append('Error: ' + errorThrown + '<br/>');
},
beforeSend: function () {
$("#Status").append('<br/>Process started.<br/>');
}
});
バッファーへの呼び出しを正しく使用しているかどうかはわかりません。コントローラーのアクション DoTask にブレークポイントを設定し、停止しないため、各タスクを正しくキューに入れていないため、バッファーへの呼び出しが正しくないようです... . それで、私は何を間違っていますか?
最初の試み(Paul Grime の解決策): 私はあなたの解決策を実行しましたが、私ができないことをいくつか変更しようとしています:
1) 私の DoTask は、http コード 200 (タスクが正常に完了した場合) または 500 (タスクが正常に完了しなかった場合) HttpStatusCodeResult(HttpStatusCode.OK)/HttpStatusCodeResult(HttpStatusCode.NotFound) を返します。 ..) doTask の結果を追加したい、例えば:
doTask がタスクを正常に完了した場合:
"結果" : "合格" => 完了 { "結果" : "合格", ...}
doTask がタスクを正しく完了していない場合:
"Result": "Failed" => done { "Result": "Failed", ...}
2) タスクをグループ化したので、最初にタスクの種類を実行するために起動し、それらが終了したら、うまくいくかどうかに関係なく、次の種類のタスクを起動する必要があります。 .. それを行うためにコードを変更する方法は?
2 回目の試行:
コントローラ:
[HttpPost]
public JsonResult GetData()
{
var data = (dynamic)null;
using (BBDDContext context = new BBDDContext())
{
data = context.MyObject.Where(o => o.TypeId == 1).OrderBy(k => k.Name).Select(obj => new
{
name =obj.Name,
description =obj.Description
}).ToList();
}
return Json(data, JsonRequestBehavior.AllowGet);
}
意見:
function getTasks() {
return ajax({
url: "/Tests/GetData/",
type: 'POST',
dataType: 'json',
contentType: "application/json; charset=utf-8"
}).then(function (data) {
// data contains a list of pairs [Name IP]
return ok(createObject("status", "ok", "op", "getTasks", "data", JSON.stringify(data)));
}, function () {
return ok(createObject("status", "fail", "op", "getTasks"));
});
}
何らかの理由で「Received GetData results...」を印刷しようとすると、最初の部分 (「status」、「ok」、「op」、「getTasks」) が失われ、「data」に関連する最後の部分のみが印刷されます。 (表示されます)。