Drupal 8:通过 AJAX 请求运行批处理
这个问题来自我最近在做的一个项目。我不得不代表用户执行一堆 API 查找,这可能需要一分钟左右的时间才能完成。API 查找的结果被缓存,因此一旦完成,站点就会非常快,不幸的是,最初的 API 查找显着减慢了页面加载速度,因此产生了问题。
我创建了一个批处理过程,以更易于管理的方式加载 API 结果,而不是仅仅在页面加载过程中进行 API 加载并让用户坐下来。这产生了另一个问题,尽管 Drupal 中的批处理运行器非常好,但仅仅向用户展示并期望他们了解正在发生的事情可能有点太多了。这让我想到是否可以通过 AJAX 回调从他们试图加载的页面运行批处理。
不得不说,这个问题的解决方法我找了好久。事实证明,以前没有人解决过这个问题(我可以看到)。
第一步是创建一个库来控制批处理的 AJAX 回调。
loader:js:
js/loader.js: {}
dependencies:
- core/jquery
- core/drupalSettings
连同名为 loader.js 的相关 JavaScript 文件。我不知道我需要在这里填写什么,所以只是一个存根,所以我首先使用最小的 AJAX 回调来创建它,该回调会触发批处理过程。
(function ($, Drupal) {'use strict';
Drupal.behaviors.account = {
attach: function attach(context, settings) {
$.ajax({
url: Drupal.url('loading/ajax'),
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function success(value) {
// 做东西...
}
});
}
};
})(jQuery, Drupal);
这是通过将其附加到页面的输出而加载到页面上的。在这种情况下,我只是使用静态插页式页面来运行 AJAX 请求。
public function myLoading() {return [
'#theme' => 'my_loading',
'#attached' => [
'library' => [
'my_module/loader',
],
],
];
}
这是一个标准的 Drupal 控制器,所以它没有做任何特别的事情。这可能在一个块或其他东西中,但我们希望将用户带到“加载”页面,同时我们从 API 获取内容,然后将它们发送回他们试图访问的页面。
最后一步是设置 AJAX 端点,以便它可以触发批处理。
public function ajaxBatchProcess() {// 设置批处理。
$this->batchService->setupLengthyBatchProcess();
// 获取我们刚刚创建的批次。
$batch =& batch_get();
// 确保完成的响应不会产生任何消息。
$batch['sets'][0]['finished'] = NULL;
// 创建batch_process(),并为它提供一个它将要去的URL。
$url = Url::fromRoute('user.page');
$response = batch_process($url);
// 将响应返回到 ajax 输出。
$ajaxResponse = new AjaxResponse();
return $ajaxResponse->addCommand(new BaseCommand('batchcustomer', $response->getTargetUrl()));
}
我错过了这里的一些复杂性,但基本上我已经将批量创建包装在一个服务中。该服务本质上是一个设置和管理批处理运行的类。该函数setupLengthyBatchProcess()本质上只是包装了batch_set($batch); 调用并且可以在提交处理程序或类似的东西中使用。批处理完成功能还报告它刚刚完成的内容,因此将其删除以防止向用户显示这些消息。
经过一番调查,我发现该batch_process()函数的结果是返回批处理运行器的路径(例如batch?id=12345&op=start)。我不想向用户显示这个,所以我不能只向 AJAX 请求返回重定向响应。
解决此问题的一种方法是在批处理设置中设置“渐进式”选项。这实际上是一次处理整个批次,这并不是我真正想做的。我们失去的(除了能够以小块处理正在处理的数据量之外)是能够告诉用户他们必须等待多长时间,因为我们无法报告我们在批处理过程中走了多远。一个简单的进度指示器非常有用,即使用户只需要等待 10 秒钟。
如果您确实想沿着这条渐进式路线走下去,那么只需更改上面代码中的几个文件,到目前为止我所展示的一切都将起作用。请注意,我不再向batch_process()函数发送 URL,因为我们不会进行任何重定向。您还需要确保当 AJAX 请求完成时,它会正确重定向,因为它目前什么都不做。
$batch =& batch_get();
$batch['progressive'] = TRUE;
$response = batch_process();
我最终做的是对 Drupal 8 的批处理运行器进行逆向工程。这使用了一个名为ProgressBar的插件,该插件基本上监视端点并报告进度。该updateCallback()函数用于更新用户的进度或执行重定向。这有效地以与 Drupal 通常运行它的方式相同的方式运行批处理。
(function ($, Drupal) {'use strict';
Drupal.behaviors.account = {
attach: function attach(context, settings) {
var progressBar = void 0;
function updateCallback(progress, status, pb) {
$('#updateprogress').html(progress + '%');
if (progress === '100') {
pb.stopMonitoring();
window.location= '/user';
}
}
function errorCallback(pb) {
}
$.ajax({
url: Drupal.url('account/loading/ajax'),
type: 'POST',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function success(value) {
progressBar = new Drupal.ProgressBar('updateprogress', updateCallback, 'POST', errorCallback);
progressBar.startMonitoring(value[0].data + '&op=do', 10);
}
});
}
};
})(jQuery, Drupal);
最终,这非常有效。当用户登录时(我们检测到他们还没有缓存),他们被发送到这个中间页面,批处理在后台运行,同时他们等待 API 调用完成。该过程会报告它已经完成了多远,一旦完成,用户就会被发送回他们的帐户页面。
以上是 Drupal 8:通过 AJAX 请求运行批处理 的全部内容, 来源链接: utcz.com/z/356140.html