После некоторого действия пользователя (например, удаление элемента) показывается
SnackBar с кнопкой "Отмена". Если успеть её нажать, то действие надо отменить.
С одной стороны, это действие короткое и можно попробовать разрулить всё в презентере.
Но тогда нужно быть внимательным с состоянием этого процесса, чтобы не продублировать
команду и корректно отменить, если нужно. С другой стороны, отмена операции - бизнес
логика, и нужно как-то учитывать это.
Как лучше это сделать?
Ответы
Ответ 1
Презентер сообщает действие интерактору только по событию: SnackBar скрылся, то есть
только после того как пользователь решил не отменять действие.
Важно заранее учесть, что пользователь может сразу после действия выйти с экрана
или приложения. Тогда надо принять решение - либо также передать действие интерактору
при деттаче вью, лтбо считать такое поведение пользователя тоже отменой действия.
В програмке есть два цикла while, как сделать так, чтобы они работали одновременно?
Ответы
Ответ 1
Используйте модуль threading:
from threading import Thread
def f():
for i in range(3):
print('Я из функции f и я несу ', i)
def f_2():
for i in range(3):
print('Я из функции f_2 и я несу ', i)
th_1, th_2 = Thread(target=f), Thread(target = f_2)
if __name__ == '__main__':
th_1.start(), th_2.start()
th_1.join(), th_2.join()
Результат:
Я из функции f и я несу 0
Я из функции f_2 и я несу 0
Я из функции f и я несу 1
Я из функции f_2 и я несу 1
Я из функции f и я несу 2
Я из функции f_2 и я несу 2
Ответ 2
from asyncio import coroutine, ensure_future, gather, get_event_loop
import time, random
def func1(a):
while a < 3:
print('func1', a)
a += 1
time.sleep(random.randrange(3))
return 'func1 = %s' % a
def func2(a):
while a < 5:
print('func2', a)
a += 1
time.sleep(random.randrange(3))
return 'func2 = %s' % a
@coroutine
def async_worker(fn, a):
r = yield from LOOP.run_in_executor(None, fn, a)
return r
@coroutine
def async_map():
workers = [ensure_future(async_worker(func1, 0), loop=LOOP),
ensure_future(async_worker(func2, 0), loop=LOOP)]
result = yield from gather(*workers, loop=LOOP)
return result
if __name__ == '__main__':
LOOP = get_event_loop()
result = LOOP.run_until_complete(async_map())
print(result)
out:
func1 0
func2 0
func2 1
func1 1
func2 2
func1 2
func2 3
func2 4
['func1 = 3', 'func2 = 5']
--
def func1():
a = 0
while a < 2:
a += 1
print('func1', a)
yield a
def func2():
b = 0
while True:
a = yield
print('func2', a)
b += a
yield b
if __name__ == '__main__':
fn2 = func2()
next(fn2)
for a in func1():
b = fn2.send(a)
print('b = %s' % b)
next(fn2)
out:
func1 1
func2 1
b = 1
func1 2
func2 2
b = 3
Как сделать так, чтоб при выборе в radio какого-то значение, то select переключался
на это же значение?
Ответы
Ответ 1
Вариант без jQuery с использованием индексов вместо value:
var select = document.querySelector('select');
var inputs = document.querySelectorAll('input[name="select"]');
for (const i in inputs) {
if (inputs.hasOwnProperty(i)) {
inputs[i].addEventListener('change', function () {
select.selectedIndex = i;
});
}
}
1
2
3
4
5
JSFiddle
C# async/await
public partial class MainWindow : Window
{
private static object sync = new object();
public MainWindow()
{
InitializeComponent();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
Random rnd = new Random();
for (int i = 0; i <= 100; ++i)
{
KeyValuePair pr = new KeyValuePair(i.ToString(),
rnd.Next(1251000, 1259999).ToString());
ProcessingTransactionAsync(pr);
}
}
private async void ProcessingTransactionAsync(KeyValuePair trn)
{
this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 1");
TestResult trnRes = await Task.Run((Func)(() =>
{
this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 2");
return this.ProcessingTransaction(trn);
}));
}
private TestResult ProcessingTransaction(KeyValuePair trn)
{
this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 3");
//Здесь ещё функции, функции, функции
Thread.Sleep(1000);
TestResult value = new TestResult();
this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 4");
return value;
}
#region Additional
private void WriteLog(string nameLogFile, string message)
{
try
{
string pathToLog = "Log";
if (!Directory.Exists(pathToLog))
Directory.CreateDirectory(pathToLog);
string filename = Path.Combine(pathToLog, string.Format("{0}.log", nameLogFile));
string fullText = string.Format("[{0:dd.MM.yyy HH:mm:ss.fff}] {1}\r\n",
DateTime.Now, message);
lock (sync)
File.AppendAllText(filename, fullText, Encoding.GetEncoding("Windows-1251"));
}
catch
{
// Перехватываем все и ничего не делаем
}
}
#endregion
}
На первой итерации в лог пишется сл.:
[21.06.2017 16:53:49.998] ----> 1
[21.06.2017 16:53:50.022] ----> 2
При 100 итерации
[21.06.2017 16:56:44.937] ----> 1
[21.06.2017 16:56:52.672] ----> 2
Что программа может делать так долго(около 8 секунд) между шагами "----> 1" и "---->
2" на 100 итерации? Можно ли это как-то исправить?
Ответы
Ответ 1
Вы запускаете в цикле одновременно 100 тасков (ProcessingTransactionAsync): вы не
дожидаетесь их окончания. Каждый из них запускает внутренний таск через Task.Run на
пуле потоков.
Пул потоков работает так: если есть свободный поток, то задание выполняется на нём.
Если нет, система пытается создать новые потоки до MaxThreads. Если потоков и так слишком
много, система думает, что вы просто создаёте задания, не дожидаясь результата, и не
создаёт новых потоков, а просто ждёт, пока какой-то из рабочих потоков не освободится,
и лишь тогда отдаёт ему задание.
Думаю, у вас случилось именно это.
Имеем строку url = 'http://site.loc/?a=1&search=abcdf';
и регулярное выражение re = /\&search\=.*?(?=\&)/g;
Только оно срабатывает, если находит за искомым словом символ &.
Если же его нет, то выражение не срабатывает.
Как мне исправить регулярное выражение, что бы оно выполнялось или до & или до конца
строки $?
Ответы
Ответ 1
Попробуйте. Символ | - это или, также для таких поисков применяется [^&]+ - любые
количеством больше 1, кроме &
console.log('http://site.loc/?search=abcdf&a=1'.match(/(\?|&)search=([^&]+)/)[2])
Ответ 2
r = /[?&]search=([^&]+)/;
console.log('http://site.loc/?search=abcdf&a=1'.match(r)[1]);
console.log('http://site.loc/?search=abcdf'.match(r)[1]);
console.log('http://site.loc/?b=1&search=abcdf'.match(r)[1]);
console.log('http://site.loc/?b=1&search=abcdf&a=1'.match(r)[1]);
// если доработать именно ваш код...
r = /&search=(.*)(?=&)*/;
// ^
console.log('http://site.loc/?b=1&search=abcdf'.match(r)[1]);
Квантификаторы можно указывать и для групп.
Ответ 3
Я понимаю, что разбор url был бы приемлем, но на данный момент мне нужно было регулярное
выражение, которое сделало бы то, что от него требуется.
Сегодня методом изучения нашел правильное решение:
re = /&search\=((.*?)(?=&)|(.*))/g; ищет от &search= до следующего &, а если не находит,
то до конца строки. Вот это мне нужно было сделать.
Для перелистывания слайдера использую cssEase:'linear' и когда навожу на элемент
- появляется box-shadow, позиция мышки остается на слайде. Слайдер при этом продолжает
скроллиться и box-shadow скроллится вместе со слайдером, но позиция мышки остается
неизменной.
$(function() {
$('.your-class').slick({
slidesToShow: 3,
slidesToScroll: 1,
autoplay: true,
autoplaySpeed: 0,
speed: 4000,
pauseOnHover: false,
cssEase:'linear'
});
});
.your-class div {
display: block;
height: 100px;
width: 800px;
}
.your-class div:hover {
-webkit-box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
}
aaaaa aaaaaaa
bbbbb bbbbbbb
ccccc ccccccc
ddddd ddddddd
eeeee eeeeeee
fffff fffffff
ggggg ggggggg
hhhhh hhhhhhh
Ответы
Ответ 1
Во время анимации перемещения :hover не срабатывает. Браузер ждет ее окончания и
эта проблема известна https://bugs.chromium.org/p/chromium/issues/detail?id=246304.
Ничего тут не поделаешь.
Возможное решение: кастомно ставить класс .hover под элемент, над которым находится мышь:
$(function () {
$('.your-class').slick({
slidesToShow: 3,
slidesToScroll: 1,
autoplay: true,
autoplaySpeed: 0,
speed: 4000,
pauseOnHover: false,
cssEase: 'linear'
});
var lastCoordinates = [0, 0];
$(document).off('mousemove').mousemove(function (e) {
lastCoordinates = [e.pageX, e.pageY];
});
$(document).on('touchmove', function (e) {
//lastCoordinates = [e.pageX, e.pageY];
});
setInterval(function () {
$('.hover').removeClass('hover');
var element = $(document.elementFromPoint(lastCoordinates[0],
lastCoordinates[1]));
if (element.closest('.your-class').length) {
element.addClass('hover')
}
}, 100);
});
.your-class div {
display: block;
height: 100px;
width: 800px;
}
.your-class div.hover {
-webkit-box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
box-shadow: 0 20px 55px 13px rgba(0, 0, 0, 0.2);
}