,
在 Web 应用中,触发后台异步批量发送短信并确保不影响用户体验,通常可以通过异步任务处理来实现。具体实现的方法有很多种,主要目的是让前台用户在请求发送短信时,不会因为短信发送过程的延时而卡住页面,从而影响用户体验。
以下是一个常见的解决方案,利用 后台异步处理 和 队列机制 来完成这一任务。
解决方案概述
- 前端:触发一个请求来发起短信任务。
- 后端:接收到请求后,将短信任务入队(异步处理),然后立刻返回给前端,告诉用户请求已提交,正在处理中。
- 任务队列:后台服务从队列中读取任务,异步批量发送短信。
- 用户体验:由于是异步任务,用户不会被阻塞,前端页面可以继续操作,甚至在后台任务完成后通过 WebSocket 或 轮询 来通知用户短信发送结果。
具体实现
1. 使用队列系统处理短信任务
通过 队列系统,你可以将所有短信发送任务加入队列,后台 worker 会异步消费队列中的任务并执行批量发送。常用的队列系统有 Redis Queue、RabbitMQ 或 Laravel Queue 等。
示例:使用 Redis Queue 处理短信发送任务
- 前提:需要安装和配置 Redis 和队列服务。
- 步骤:
- 在前端触发请求,告诉后端开始短信发送。
- 后端将任务加入队列。
- 后台的 worker 会从队列中消费任务,并开始批量发送短信。
前端代码:触发后台请求
// 假设你有一个触发按钮来发送批量短信
document.getElementById('sendSmsButton').addEventListener('click', function() {
fetch('/api/send-bulk-sms', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ phoneNumbers: ['12345678901', '9876543210'], message: 'Hello World' })
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert('短信发送任务已提交,稍后会处理!');
} else {
alert('任务提交失败,请稍后重试!');
}
});
});
后端代码:处理短信发送请求并入队任务(使用 Laravel 框架为例)
// routes/web.php
Route::post('/api/send-bulk-sms', 'SmsController@sendBulkSms');
// SmsController.php
use App\Jobs\SendBulkSms;
class SmsController extends Controller
{
public function sendBulkSms(Request $request)
{
// 获取前端请求的电话号码和消息内容
$phoneNumbers = $request->input('phoneNumbers');
$message = $request->input('message');
// 将发送短信的任务加入队列
SendBulkSms::dispatch($phoneNumbers, $message);
return response()->json(['success' => true, 'message' => '短信发送任务已提交']);
}
}
队列任务:SendBulkSms
任务类
// app/Jobs/SendBulkSms.php
namespace App\Jobs;
use App\Services\SmsService; // 你的短信服务类
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendBulkSms implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $phoneNumbers;
protected $message;
// 构造函数接收短信相关的参数
public function __construct($phoneNumbers, $message)
{
$this->phoneNumbers = $phoneNumbers;
$this->message = $message;
}
// 任务处理方法,发送短信
public function handle(SmsService $smsService)
{
foreach ($this->phoneNumbers as $phone) {
// 假设 SmsService 已经封装了短信发送的逻辑
$smsService->send($phone, $this->message);
}
}
}
后台消费任务
确保你已经配置并启动了队列消费服务。例如,在 Laravel 中,可以使用 php artisan queue:work
来启动队列消费者。
php artisan queue:work
这样,队列中的任务就会被后台的 worker 消费并执行。通过 SendBulkSms
任务类中的 handle()
方法,你可以批量发送短信,而不会影响用户体验。
2. 确保后台任务不会阻塞
为了确保后台任务不会阻塞,可以通过以下方式处理:
- 异步任务处理:使用队列系统如 Redis Queue、RabbitMQ、Beanstalkd 等来处理短信任务。这些队列系统会在后台线程中处理任务,不会占用主线程。
- 分批次处理:如果短信数量非常大,最好将发送任务分批处理,每次处理一定数量的短信,避免一次性任务超时或导致资源紧张。
3. 通知用户短信发送状态
为了保持用户体验,你可以通过以下两种方式通知用户:
3.1 使用 轮询
在前端页面上定期检查短信任务的处理状态。如果任务完成,向用户显示成功消息。
function checkSmsStatus(taskId) {
setInterval(function() {
fetch('/api/sms-status/' + taskId)
.then(response => response.json())
.then(data => {
if (data.status === 'completed') {
alert('短信已发送完成!');
}
});
}, 5000); // 每5秒轮询一次
}
3.2 使用 WebSocket
通过 WebSocket 通知前端短信发送的进度或结果。这种方式比轮询更高效,因为它是实时推送的。
- 在后台任务处理过程中,可以通过 WebSocket 向前端推送消息通知。
- 使用 Laravel WebSockets 或 Socket.io 等工具来实现。
4. 总结
通过使用队列系统(如 Redis Queue 或其他消息队列)来异步处理短信任务,你可以确保:
- 用户请求一发起,立即返回处理结果,而不会阻塞用户界面。
- 后台异步发送短信时,不会影响用户体验。
- 可以通过轮询或 WebSocket 实时向用户反馈短信发送状态。
这种设计可以显著提高用户体验,避免长时间的请求阻塞和页面卡顿。