Promise.all()
asyncX()
возвращали промисы:const yourXFunction = (async1, async2, async3, someCallback) => {
let latest; // последнее значение остаётся
Promise.all([
async1().then(v => {latest = 1; return v;}),
async2().then(v => {latest = 2; return v;}),
async3().then(v => {latest = 3; return v;}),
]).then(results => {
console.log("Last was async" + latest);
someCallback(results[latest - 1]);
});
}
const yourXFunction = (async1, async2, async3, someCallback) => {
let latest; // последнее значение остаётся
Promise.all([
wrap(async1).then(v => {latest = 1; return v;}),
wrap(async2).then(v => {latest = 2; return v;}),
wrap(async3).then(v => {latest = 3; return v;}),
]).then(results => {
someCallback(results[latest - 1]);
});
}
const wrap = (f) => new Promise((res, rej) => f(res));
const async1 = (cb) => {
setTimeout(() => {
cb(1);
}, 4000);
};
const async2 = (cb) => {
setTimeout(() => {
cb(13);
}, 6000);
};
const async3 = (cb) => {
setTimeout(() => {
cb(5);
}, 3000);
};
const someCallback = (val) => console.log(val);
yourXFunction(async1, async2, async3, someCallback);
// через 6 секунд выведет "13"
// так не сработает:
const response = '{"success":1,"data":"{\"esiaId\":null,\"legalMunicipality\":{\"id\":12,\"name\":\"Энгельс\"},\"factMunicipality\":{\"id\":12,\"name\":\"Энгельс\"},\"is_subscribed\":false,\"subscriptions\":null}"}';
// а вот так всё получится:
const response2 = '{"success":1,"data":"{\\\"esiaId\\\":null,\\\"legalMunicipality\\\":{\\\"id\\\":12,\\\"name\\\":\\\"Энгельс\\\"},\\\"factMunicipality\\\":{\\\"id\\\":12,\\\"name\\\":\\\"Энгельс\\\"},\\\"is_subscribed\\\":false,\\\"subscriptions\\\":null}"}';
console.log(response2);
const parsed = JSON.parse(response2);
const data = JSON.parse(parsed.data);
console.log(data.legalMunicipality.name); // Энгельс
time()
if .. else
и выводите релевантную строку.if()
проверяет только условие существования файла или директории. А try-catch
обработает бОльшее число ситуаций: если это не файл, а директория, если права не позволяют читать, если устройство гакнулось и не прочиталось.# Вариант 1:
f getFileContent(filename){
if (!file_exists(filename)) {error: file not found}
return file_content(filename)
}
# Вариант 2:
f getFileContent(filename){
try return file_content(filename)
catch FileNotFoundException {error: file not found}
}
if
отличается тем, что проверяет предусмотренные варианты, а исключения кидаются в непредусмотренных. Все бросаемые исключения надо документировать, чтобы их кто-то где-то, в итоге, поймал.const someObject = {a:'value A'};
const arr1 = [1, 'test', someObject];
const arr2 = [100, 200, 'testing', {a:'value A'}];
const arr3 = [1e3, someObject];
const arrays = [arr1, arr2, arr3];
const dict = new Map();
const addArray = (arr, label) => {
for(let i=0, len=arr.length; i<len; i++) {
const key = arr[i];
if (dict.has(key)) return [key, dict.get(key), label];
dict.set(key, label);
}
}
for (let i=0, len = arrays.length; i<len; i++) {
const check = addArray(arrays[i], `arr${i+1}`);
if (!check) continue;
console.log(`Value ${check[0]} found in arrays ${check[1]} and ${check[2]}`);
break;
}
// Value [object Object] found in arrays arr1 and arr3
Class Names
Class names should normally use the CapWords convention.
The naming convention for functions may be used instead in cases where the interface is documented and used primarily as a callable.
Note that there is a separate convention for builtin names: most builtin names are single words (or two words run together), with the CapWords convention used only for exception names and builtin constants.
let
и const
– объявлений с блочной областью видимости – без IIFE можно обходиться там, где их заводили только ради чистоты глобальной о.в.:// раньше
(function(){
var a = 1;
var b = 2;
b *= 2;
console.log(a + b);
})();
// здесь a и b уже не видны
// теперь можно просто заключить часть кода в "блок"
// и все переменные останутся в Вегасе:
{
const a = 1;
let b = 2;
b *= 2;
console.log(a + b);
}
[0, 1)
— квадратная скобка означает включение числа, круглая – «дырку», исключение.x - 0.5
(включая) до x + 0.5
(исключая) округлит до целого x
. Можно записать так: [x-0.5, x+0.5)
min
до max
в описанном варианте старается сгладить вероятности всех целых до равных. Math.random()
. При этом сама "1" не участвует, но в данном случае это маловажно. Далее умножаем да диапазон, напр. на 4, и с помощью Math.round()
делим отрезки этой дорожки в кучки для каждого целого. Кучки по краям получатся меньше остальных.[0, 1)
просто умножить на 4 и округлить Math.round()
– будет выдавать случайные целые [0, 4]
(а не до 3). И как неравновероятно!0 1
[...................)
0 1 2 3 4
00011111222223333344o
Math.round()
разбивает пополам расстояние между двумя целыми, получится не 4 а 5 кучек. При чём в крайние, 0 и 4, попадёт всего по пол-интервала. Их вероятность будет 1/2 от полноценных вероятностей для 1, 2 и 3.min-0.5
до max+0.5
, чтобы после Math.round()
вероятности всех целых были одинаковы.Math.round()
можно недолюбливать и вместо него округлять вниз, Math.floor() – так случайное целое, как в вашем вопросе, можно получить проще const rand = (min, max) => min + Math.floor(Math.random() * (max - min + 1));
alert( rand(1, 3) );
[ .. )
– включающими начало, но исключающими конец. Например, randomInteger(min, max)
никогда бы не вернула max
. А это задание вышло такое себе, нетрадиционное, у них )