loading++ loading-- loading===0
- если такой "застрянет", значит где-то ошибка в логике.:)AbortSignal
в axios
можно с помощью интерцептора.async
(Promise
) отмены в красивом виде не предусмотрели. yield
вместо async
+ обёртки), которое позволяет остановить всё на любом моменте извне, ничего не пробрасывая и не подготавливая. Однако это костыль, требует всяких уродливых обёрток, не очевидного поведения и плоховато дружит с типизацией. composer require spiral/roadrunner-bundle
<?php
// src/DBAL/ConnectionWrapper.php
namespace App\DBAL;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Configuration;
use Doctrine\Common\EventManager;
class ConnectionWrapper extends Connection
{
/**
* @var int
*/
private $reconnectAttempts = 3;
public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null)
{
parent::__construct($params, $driver, $config, $eventManager);
}
public function prepare($sql)
{
$this->ping();
return parent::prepare($sql);
}
public function executeQuery(string $sql, array $params = [], $types = [], ?QueryCacheProfile $qcp = null)
{
$this->ping();
return parent::executeQuery($sql, $params, $types, $qcp);
}
public function executeUpdate(string $sql, array $params = [], array $types = [])
{
$this->ping();
return parent::executeUpdate($sql, $params, $types);
}
public function ping(): bool
{
if ($this->isConnected() && $this->getWrappedConnection()->ping()) {
return true;
}
$this->close();
for ($i = 0; $i < $this->reconnectAttempts; $i++) {
try {
$this->connect();
if ($this->getWrappedConnection()->ping()) {
return true;
}
} catch (\Exception $e) {
// ещё разок
}
}
throw new \RuntimeException("Unable to reconnect to the database.");
}
}
# config/packages/doctrine.yaml
doctrine:
dbal:
# обычные настройки
url: '%env(resolve:DATABASE_URL)%'
driver: 'pdo_mysql'
server_version: '8.0'
charset: utf8mb4
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
# наша обёртка
wrapper_class: App\DBAL\ConnectionWrapper
composer require spiral/roadrunner-symfony
composer require spiral/roadrunner-doctrine
class Type
{
isArray() {}
}
export default Type
class Dialog
{
show() {}
}
export default Dialog
import Type from './Type.js'
import Dialog from './Dialog.js'
export { Type, Dialog }
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* Получить данные пользователя, связанные с этим пользователем.
*/
public function userData()
{
return $this->hasOne(UserData::class);
}
}
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserData extends Model
{
use HasFactory;
/**
* @var array<int, string>
*/
protected $fillable = [
'phone_number',
];
/**
* Получить пользователя, которому принадлежат эти данные.
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
use App\Models\User;
use App\Models\UserData;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
DB::transaction(function () {
// 1. Создаем пользователя (User)
$user = User::create([
'name' => 'Вася Пупкин',
'email' => 'uasya@fsb.ru',
'password' => Hash::make('12345'),
]);
// 2. Создаем данные пользователя (UserData) и связываем их с пользователем
$user->userData()->create([
'phone_number' => '112',
]);
});