Страницы

Поиск по вопросам

вторник, 9 апреля 2019 г.

Работа промисов

Добрый Вечер. Наткнулся на такой пример с промисами :
var promise = new Promise(function(resolve, reject) { resolve(1); });
function logger(message) { console.log(message); }
promise .then(logger) .then(logger(2)) .then(() => logger(3));
В результате на выходе результат - 2, 1, 3. Правильно ли я понимаю, что перед тем, как начинать выполнять данный код, с начала отдается приоритет вызову функции logger ? Именно поэтому в результате с начала идет 2 ? Функция logger, возвращает undefined, а в консоль пишет 2. Затем, после выполнения промиса, после первого then (который вернул вместо промиса undefined), в консоль запишется 1, а уж затем вернется 3.


Ответ

Promise нужен для выполнения действий со значением, которого на момент определения действий может ещё не быть. Это чтобы было немножко понятнее, какова цель всего происходящего здесь.
Ещё обращу внимание, что существующие реализации JS однопоточны и переключения в пределах одной исполняющей среды (скажем, вебворкеры я считаю отдельными средами) происходят только между функциями, после завершения выполнения каждой. Разумеется, функции внутри себя могут синхронно (непосредственно) вызывать другие функции, но многое в JS API опирается на асинхронные вызовы, которые лишь приводят к добавлению в очередь событий и, когда-нибудь, обработку циклом событий.
Ну да к делу.
Вывод у вас происходит при вызове функции logger. Посмотрим, когда она вызывается.
Сначала выполняется наружный код. Определение цепочки промисов. Пока выполнение этого участка не дойдёт до самого конца, никакая другая функция вызвана по какому-либо событию (вроде разрешения промиса, что здесь происходит) не будет.
promise .then(logger) .then(logger(2)) .then(() => logger(3));
В первом вызове then аргументы разрешаются в значения напрямую, без вычислений. Никаких вызовов logger там не происходит. Пока что. Во втором вызове then аргумент уже выражение, требующее вычисления перед передачей: вызов функции logger. Тут-то и вызывается logger(2) и выводится 2 А возвращается из logger... ничего, что снаружи видно как undefined, которое функцией не является а потому приводит к "сквозному пробрасыванию" результата в следующий then (если таковой, как здесь, имеется), поскольку:
If the first argument is omitted or provided a non-function, the new Promise that is created simply adopts the fulfillment state of the Promise that then is called on (if it becomes fulfilled). Если первый аргумент не передан, или в нём передана не функция, то промис наследует состояние разрешения у промиса, на котором then был вызван (если он разрешается). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
Я б сказал, что игнорирование типа аргумента в then это грубый хак, сбивающий с толку и склоняющий к злоупотреблениям, но у него могут быть свои мотивы. Без большой необходимости кормить в then не-функции не стоит. В третьем вызове аргумент является функциональным выражением (стрелочной функцией, если точно), но для его вычисления вызовы logger не нужны, т. к. его результатом является функция, которая при вызове (но не создании!) вызывает logger и выводит что-то в консоль. А на этом этапе эта функция лишь создалась.
А потом уже управление переходит внутрь, поскольку промис требует запуска, его событие ждёт своей очереди на обработку. В зависимости от другого выполняющегося в той же машине JS-кода может быть и не сразу, но в рамках примера другого кода нет, так что тут — сразу внутрь цепочки.
Сначала вызывается функция из конструктора Promise. Она приводит к разрешению промиса со значением 1 Затем вызывается logger с аргументом, полученным из прошлого промиса: получается logger(1). А потому происходит вывод 1, а промис разрешается со значением undefined (т. к. функция ничего не вернула).
When a value is simply returned from within a then lambda, it will effectively return Promise.resolve() Затем сталкиваемся с пустым промисом, образованным без функции... фиг знает, что там внутри ещё происходит, но результат прошлого разрешения промиса (undefined) просто считается результатом и у этого и передаётся далее, состояние промиса (разрешился) при этом сохраняется. Затем функция () => logger(3) вызывается с аргументом undefined, но JS наплевать на лишние аргументы и в результате успешно выполняется тело функции, выполняется logger(3) и выводится 3

Поиск значение обьекта в массиве

Есть массив с обьектами
data = [{service_id: 7777}, {service_id:9999}]
у меня есть допустим переменная с айди
var myid = 9999
как мне проверить существование этого ади в массиве ?
средствами angularjs или javascript


Ответ

Вот пример:
var data = [{service_id: 7777}, {service_id:9999}] function getServicebyId(id) { return data.filter( function(data) { return data.service_id== id}); } var myid = 9999 var found = getServicebyId(myid); alert(found)

считать значения переменных в словарь из строки вида: “key1=value1 key2=value2 key3=value3”

Вводится строка виде "a=1 b=2 c=3". Необходимо считать значение переменных а,b,c в эти переменных. Проблема в том, что эти значения могут быть вперемешку(Не a,b,c, а b,a,c). Желательно, сохранить вообще всё это в словарь, но сойдёт и в переменные


Ответ

Вот записывает в словарь с ключами 'a', 'b' и 'c' и соответствующими им значениями:
d = {i.split('=')[0]: int(i.split('=')[1]) for i in input().split(' ')} print(d)
Или вот так:
d = {} for i in input().split(' '): spl = i.split('=') d[spl[0]] = int(spl[1]) print(d)

Получение данных из потока

Приветствую. Пытаюсь получить данные из потока.
process.stdin.setEncoding('utf8');
process.stdin.on('readable', () => { let chunk = String(process.stdin.read()); console.log(chunk); });
Мне возвращается
Input: 10 2 Your output: 10 2 null
Как избавиться от null?


Ответ

Как вариант, проверить, что process.stdin.read() вернул что-то полезное (не null).
Естественно, проверить надо до каста к строке, а не после. Примерно так:
process.stdin.on('readable', () => { var chunk = process.stdin.read();
if (!chunk) { return; }
chunk = "" + chunk;
console.log(chunk); });

Правильная нумерация ПО?

Есть версия ПО 2.9.9
Нужно выпустить новую версию, при этом не хотелось бы переходить на 3.0 Так и не смог разобраться, под какой версией выпустить ПО?
2.9.10? 2.10.1? 2.9.91?
Да так, чтобы было понятно людям, что эта версия новее предыдущей.


Ответ

Проблема: вы руководствуетесь принципами визуальной упорядоченности при установке версии. Версионирование не имеет никаких связей с визуальной упорядоченностью. Конфликт: вы не можете выбрать между виузальной упорядоченностью, которая говорит вам сделать 3.0.0, и принципом мажорного релиза, который осознаете скорее всего по-своему, но понимаете, что мажорный релиз это не "когда все цифры после первой становятся девятками". Решение: выбрать только одно из двух, потому что принцип мажорной версии запрещает вам скакать, как получится, а визуальная упорядоченность не дает вам использовать двузначное число в качестве одного из компонентов версии.
Как все-таки хоть немного программист я могу лишь призвать сделать выбор в пользу разумного назначения версии. Насколько понял, вы уже читали про семантическое версионирование, но, судя по комментарию, думаю, что попытаться адаптировать конвенцию для вас стоит.
Семантическая версия состоит из трех номеров: major, minor, patch. Они различаются следующими вещами:
patch-версия инкрементируется при выпуске релиза, закрывающего баги minor-версия инкрементируется при выпуске релиза с новым функционалом, не затрагивающем старый major версия инкрементируется при выпуске релиза, которым невозможно пользоваться так, как прежде
Поэтому определение "какую версию мне использовать" превращается в довольно простой условный блок:
Релиз содержит только багфиксы? Инкрементируется patch-компонент, 2.9.10 Релиз содержит нововведения, но старый функционал остался прежним? 2.10.0 Релиз содержит нововведения, которые меняют способ использования старого функционала? 3.0.0
Отвечая на вопрос, который тут же появляется - "мне что, инкремнтировать major-версию каждый раз, когда я ломаю обратную совместимость?". Ответ на этот вопрос - да, major-версия должна выпускаться каждый раз, когда какие-то вещи ломаются; это не игра в поддавки и визуальную упорядоченность. Если вас заботит скорость выпуска major-версий - это значит, что вы ломаете слишком много вещей, и какие-то обновления стоит придерживать в ветке до того, как появится моральная готовность выпустить новый major-релиз; на адаптацию к этой модели уйдет некоторое время, но на деле это всего лишь цифры, между которыми нет никакой разницы, версия 2.х.х или 17.х.х - для конечного потребителя это не так важно как то, сможет ли он пользоваться новой версией так же, как старой.
Не пытайтесь воспринимать 2.9.9. как 299. Это не число и не поддается правилам инкрементирования чисел.

Запись int в массив byte[] (NET3.5)

Как и при помощи какого метода можно записать целочисленное int в byte[]
Ограничен 3.5, DataInputStream/DataOutputStream - не подходят.
Предполагаемый код:
// Записать этот инт int _sizeBlock = 10489; // В этот массив byte[] info = new byte[4];


Ответ

int _sizeBlock = 10489;
byte[] info = BitConverter.GetBytes(_sizeBlock);
документация по методу
Возможен случай, когда на компьютере используется обратный порядок для хранения байт. Необходимо проверять флаг BitConverter.IsLittleEndian, если он установлен в true "перевернуть" байты в массиве.
if (BitConverter.IsLittleEndian) Array.Reverse(info);

Как правильно перевести секунды в формат HH:mm:ss?

Получаю продолжительность видео с ВК в секундах. Никак не могу перевести их в формат HH:mm:ss
Вот мой метод
public String secToStr(int duration){ SimpleDateFormat df = new SimpleDateFormat("hh:mm:ss"); String time = df.format(new Date(duration)); return time; }
Любой duration переводится в 3 часа. Что я делаю не так? Как можно это сделать двумя-тремя строчками?


Ответ

Разобрался. Вот так надо
public String secToStr(int duration){ return String.format("%02d:%02d:%02d", duration / 3600, duration / 60 % 60, duration % 60); }