Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   promises. почему так запилено? (https://javascript.ru/forum/misc/57560-promises-pochemu-tak-zapileno.html)

javaQest 09.08.2015 14:17

promises. почему так запилено?
 
Че-то я думаю-думаю, и не могу понять, почему в JS (после стольких лет ожиданий и надежд от избавления от callback-hell), запилили настольок уродливую парашу? Ведь, по идее, JS -- это ООП язык, а в Ъ асинхронные сообщения запиливаются по другому.

Суть в том, что, чтобы наше дерьмо возвратило обещание, нам надо предварительно это подготовить с помощью new Promise, тогда как в нормальных ООП-языках, мы имеем возможность асинхронно отправить сообщение независимо от его реализации.

Почему так сделали? Причина в каких то ограничениях языка? Или просто дезигнеры че-то попутали?

Aetae 09.08.2015 15:07

Хз, порой кажется, что увидали они callback-hell, ужаснулись и зафигачили первое, что пришло в голову. Symbol тоже мне кажется тотальным overmind'ом.
Но там вроде теоретически предположительно наверное скорее всего должны сидеть умные ребята, может это мы просто тупые чего-то недопонимаем?

Erolast 09.08.2015 15:09

Обещания - это не финальное решение для обеспечения удобной работы с асинхронщиной, а лишь шаг на пути к нему. Сейчас идет разработка фичи async functions, которая обеспечит асинхронную работу без увеличения стека, с нормальным синтаксисом и перехватом ошибок.

Выглядит так:
async function loadUser(id) {
  let user;
  
  try {
    let response = await fetch(`/api/users/${id}`);
    user = response.body;
  } catch (error) {
    console.error(error);
  }

  return user;
}

Новейший текст спецификации - http://tc39.github.io/ecmascript-asyncawait/.

Это то?

Aetae 09.08.2015 15:19

Erolast, да знаем про async - нормальное решение. Знаем и почему промисы - обратная совместимость. И всё же и всё же...

javaQest 09.08.2015 15:36

Цитата:

Сообщение от Erolast
Это то?

Не знаю, надо осилить сначала документ. Я вот парралельно пишу на Io (это который язык, не js-фреймверк), там все вообще элементарно делается, типа
someMethod := casualMethod(some code returns some value)
casualVar := someMethod
aFuture := @someMethod

aFuture println
casualVar ptintln
1 println

// выхлоп будет

>>some value
>>1
>>some value // -- из фьючера

подозреваю, что это не совсем то. Во всяком случае, async/await -- точно не то

Erolast 09.08.2015 15:44

Цитата:

Не знаю, надо осилить сначала документ.
Вот в помощь: http://pouchdb.com/2015/03/05/taming...-with-es7.html

javaQest 09.08.2015 15:50

Erolast,
Спасибо, не могу плюсануть в карму, форум, наверное глючит, пишет должны добавить кому то еще, я добавил Aetae, он один х*й, не дает. разлогинивание тоже не помогло, а плюсовал я тебе, ЕМНИП, вчера, так что извиняй:)

UPD А не, добавилось вроде, че то я запутался, может не я плюсанул, ну ладно, х с ним.

Safort 09.08.2015 16:02

Цитата:

Сообщение от javaQest (Сообщение 383414)
Erolast,
Спасибо, не могу плюсануть в карму, форум, наверное глючит, пишет должны добавить кому то еще, я добавил Aetae, он один х*й, не дает. разлогинивание тоже не помогло, а плюсовал я тебе, ЕМНИП, вчера, так что извиняй:)

UPD А не, добавилось вроде, че то я запутался, может не я плюсанул, ну ладно, х с ним.

Повторно можно поставить плюс только после того, как несколько раз другим изменишь карму.
//Плюсанул я, но это всё не важно)

javaQest 09.08.2015 16:05

Safort,
Детсад какой-то. 2 раза не прокатило, поэтому, попытки прекращаю, как то смешно получается, можно покраснеть от этого нелепого конфуза:)

Erolast 09.08.2015 16:31

Да, система кармы тут, по меньшей мере, странная - ни для выражения благодарности, ни для саморегуляции не годится) Запилили бы хотя бы обычные лайки с указанием числа у каждого поста - я считаю, куда лучше б было.

EmperioAf 09.08.2015 17:58

Цитата:

Сообщение от Erolast
система кармы тут, по меньшей мере, странная

ОФФТОП:
На астрофоруме повторно + можно ставить только через 72 часа. Мне кажется было бы разумно

KosBeg 09.08.2015 21:35

Цитата:

Сообщение от Safort
Повторно можно поставить плюс только после того, как несколько раз другим изменишь карму.

если уточнить после пятого раза изменения кармы другому)
я как-то одному челу карму дрочил, только три раза минусанул, потом психанул :)

KosBeg 09.08.2015 21:39

И по теме - а чем промисы(не называйте их обещаниями, не трахайте мой девственный мозг)))) так не удобны? - http://learn.javascript.ru/promise

Erolast 10.08.2015 09:17

Удобность - понятие относительное. Относительно традиционных коллбеков - да, штука классная. Относительно async/await - то еще говно:

//async/await
async function loadUser(id) {
  let user;
   
  try {
    let response = await fetch(`/api/users/${id}`);
    user = response.body;
  } catch (error) {
    console.error(error);
  }
 
  return user;
}


//Promises
function loadUser(id) {
    return new Promise((resolve) => {
        fetch(`/api/users/${id}`).then((response) => {
            return response.body;
        }).catch((error) => {
            console.log(error);
            return undefined;
        }).then((user) => {
            resolve(user);    
        });
    });
}


И это простейший пример, без нескольких поочередных запросов и без циклов.

KosBeg 10.08.2015 17:40

Цитата:

Сообщение от Erolast
Относительно традиционных коллбеков - да, штука классная

вот именно!) но сейчас, увы, мало кто юзает es6...
=========================
До Babel
//async/await
async function loadUser(id) {
  let user;
   
  try {
    let response = await fetch(`/api/users/${id}`);
    user = response.body;
  } catch (error) {
    console.error(error);
  }
 
  return user;
}

После Babel
//async/await
"use strict";

function loadUser(id) {
  var user, response;
  return regeneratorRuntime.async(function loadUser$(context$1$0) {
    while (1) switch (context$1$0.prev = context$1$0.next) {
      case 0:
        user = undefined;
        context$1$0.prev = 1;
        context$1$0.next = 4;
        return regeneratorRuntime.awrap(fetch("/api/users/" + id));

      case 4:
        response = context$1$0.sent;

        user = response.body;
        context$1$0.next = 11;
        break;

      case 8:
        context$1$0.prev = 8;
        context$1$0.t0 = context$1$0["catch"](1);

        console.error(context$1$0.t0);

      case 11:
        return context$1$0.abrupt("return", user);

      case 12:
      case "end":
        return context$1$0.stop();
    }
  }, null, this, [[1, 8]]);
}

немножко "не удобный" код...
===================
ПОМОГИТЕ!
Как при помощи fetch отправить POST запрос?!
я делаю так
var result = fetch('server.php?tesh=gjkhkj', {  
    method: 'post',  
    body: 'test=kosbeg&kosbeg=test'
  })

      result.then(function(response) {
        return response.text()
      }).then(function(text) {
        console.log(text)
      })['catch'](function(ex) { // так ['catch'], а не так .catch из-за корявого полифила...
        console.log('fail')
      })
}

на сервере так
<?php
print_r($_GET).'/n';
print_r($_POST).'/n';

к консоли массив $_POST пустой...
как исправить?!

KosBeg 10.08.2015 17:58

PS: мир сошел с ума: я использую fetch вместо православного аякса,
и я учусь писать код на es6...

проблемму решил:
var result = fetch('server.php?tesh=gjkhkj', {  
    method: 'post',  
*!*
     headers: {  
      "Content-type": "application/x-www-form-urlencoded; charset=UTF-8"  
    },  
*/!*
   body: 'test=kosbeg&kosbeg=test'
  })

      result.then(function(response) {
        return response.text()
      }).then(function(text) {
        console.log(text)
      })['catch'](function(ex) { // так ['catch'], а не так .catch из-за корявого полифила...
        console.log('fail')
      })
}

БЛЯ! довбаные хедеры не поставил...

javaQest 10.08.2015 18:50

KosBeg,
Ну и чем это лучше обычного
fetch=function(url, body){
  return new Promise(function(resolve, reject){
    with(new XMLHttpRequest){
      open("POST", url) 
      send(body)
      onreadystatechange=function(){
        if(readyState==4){
         if(status!=200) return reject(status)
         resolve(responseText)
        }
      }
    }
  })
}


fetch("foo", "foo=bar&bar=baz")
 .then(function(s){alert(s)})
 .catch(function(s){console.log(s)})

?

Erolast 10.08.2015 19:48

Цитата:

Сообщение от javaQest (Сообщение 383519)
KosBeg,
Ну и чем это лучше обычного
fetch=function(url, body){
  return new Promise(function(resolve, reject){
    with(new XMLHttpRequest){
      open("POST", url) 
      send(body)
      onreadystatechange=function(){
        if(readyState==4){
         if(status!=200) return reject(status)
         resolve(responseText)
        }
      }
    }
  })
}


fetch("foo", "foo=bar&bar=baz")
 .then(function(s){alert(s)})
 .catch(function(s){console.log(s)})

?

Как минимум тем, что ты пишешь какой-то сраный код в нагрузку, а родной fetch работает уже из коробки (для старья, конечно, придется подключать полифилл, но, тем не менее, этот полифилл УЖЕ написан за тебя).

Ну, и вдобавок есть такие мелочи, как работа в строгом режиме, уместность в модульном окружении, поддержка отличных от GET запросов, поддержка установки заголовков, чтения заголовков и т.д.

Кстати, чо там с множественным наследованием и решением задачи, которую тебе Кобеззза в ответ задал?

Erolast 10.08.2015 20:15

Цитата:

После Babel немножко "не удобный" код...
А зачем ты его читаешь?) Его запускать надо.
Но, в принципе, да - без использования ES Harmony аналогичный по функциональности код выглядел бы именно так.


Цитата:

я использую fetch вместо православного аякса
Лол, а чем fetch не Asynchronous JavaScript and XML? Наверное, ты имел в виду "вместо интерфейса XMLHttpRequest"?)


Цитата:

// так ['catch'], а не так .catch из-за корявого полифила...
Полифилл тут не при чем. Дело в том, что catch - это ключевое слово, а до ES6 обращения через точку к свойствам, названных ключевым словом, было запрещено. Пропускай через babel, он будет транспиллить в скобочную нотацию там, где надо.


Цитата:

var result = fetch('server.php?tesh=gjkhkj', {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'test=kosbeg&kosbeg=test'
})
Ты как-то через задницу делаешь. Во-первых, не проще ли отправлять JSON?
fetch('server.php?tesh=gjkhkj', {
  method: 'post',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    test: 'kosbeg',
    kosbeg: 'test',
  })
})

Во-вторых, зачем указывать кодировку UTF8 в content-type? Она же и так дефолтная.

Вобще, загляни на https://github.com/github/fetch#usage, там весьма хорошая памятка.

javaQest 10.08.2015 20:45

Цитата:

Сообщение от Erolast
Кстати, чо там с множественным наследованием и решением задачи, которую тебе Кобеззза в ответ задал?

седня устал, завтра занят, может на днях гляну. Мне честно говоря, читать твой код -- серпом по яйцам. Переписал бы ты его традиционным синтаксисом. Неохота мне в эти перделки вникать, тем боле я знаю, что это говно мне не нужно и никогда не будет нужно. А я мозг забивать абы чем не люблю.

javaQest 10.08.2015 20:48

Цитата:

Сообщение от Erolast
УЖЕ написан за тебя

Это скорей минус, а не плюс. свой код я знаю, и могу гибко его подстроить под свои нужды. имею представленииие о перформансе и тп. тем более, 99% этих либ написаны мартышками, меня блевать тянет с их исходников.

javaQest 10.08.2015 20:54

Цитата:

Сообщение от Erolast
Дело в том, что catch - это ключевое слово

Лишнее подтверждение маразматичности этих пейсателей кода. Что нельзя было другое слово придумать? onError, например. Тем более, семантически, там catch'ем и не пахнет.

KosBeg 10.08.2015 21:17

Цитата:

Сообщение от Erolast
Во-вторых, зачем указывать кодировку UTF8 в content-type? Она же и так дефолтная.

пример нашел на хабре...
Цитата:

Сообщение от Erolast
Вобще, загляни на https://github.com/github/fetch#usage, там весьма хорошая памятка

ну так бля, я от туда пришел)
я юзаю именно этот полифил
Цитата:

Сообщение от Erolast
Наверное, ты имел в виду "вместо интерфейса XMLHttpRequest"?)

ну да) как-то так)
Цитата:

Сообщение от Erolast
не проще ли отправлять JSON?

не проще, я просто не могу понять как его принять на сервере)
моя тупость зашкаливает)

KosBeg 10.08.2015 21:17

Цитата:

Сообщение от javaQest
Это скорей минус, а не плюс. свой код я знаю, и могу гибко его подстроить под свои нужды. имею представленииие о перформансе и тп. тем более, 99% этих либ написаны мартышками, меня блевать тянет с их исходников.

ну не скажи)
лично я считаю что даный полифил не хуже своего кода, над ним работаю ребята в 100 раз круче тебя, и они то знают толк в извращениях)

javaQest 10.08.2015 21:35

Цитата:

Сообщение от KosBeg
я просто не могу понять как его принять на сервере)

для сервера это обычная строка. есть специальные парсеры, для твоего языка, наверняка тоже есть. принимай, обрабатывай. Можешь и вручную распарсить.

С другой стороны, если он тебе не нужен, можешь не заморачиваться. Абсолютно по*ю каким форматом сервер обменивается с клиентом, главное, чтобы тебе было удобно. Просто json -- это стандарт. Если ты сам себе хозяин, можешь положить на стандарты.

KosBeg 11.08.2015 13:10

Цитата:

Сообщение от javaQest
есть специальные парсеры, для твоего языка, наверняка тоже есть. принимай, обрабатывай. Можешь и вручную распарсить.

да я в курсе - json_encode($data), json_decode($data)
Цитата:

Сообщение от javaQest
для сервера это обычная строка.

я не могу принять json на сервере так как массив $_POST пустой)

я не знаю как принять его)
хотя например можно так
let result = fetch('server.php?cool=javascript', {  
  method: 'post',
  headers: {
      "Content-type": "application/x-www-form-urlencoded"  
  },
  body: 'param=' + JSON.stringify({
    javascript: 'cool',
    es_modern: '6 aka 2015',
  })
})

 result.then(function(response) {
    return response.text()
 }).then(function(text) {
    console.log(text)
 })
}


KosBeg 11.08.2015 13:16

Общем как меня не учи - я делаю так)
function getContent(timestamp) {

  toQueryString = function(data) {
    var query = '',
      i, push = function(key, value) {
        query += encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';
      },
      key, value;
    for (key in data) {
      if (!Object.hasOwnProperty.call(data, key)) {
        continue;
      }
      value = data[key];
      if ((typeof(data) === "object") && (data instanceof Array)) {
        for (i = 0; i < value.length; i++) {
          push(key, value[i]);
        };
      } else {
        push(key, data[key]);
      };
    };
    return query.replace(/&$/, '').replace(/%20/g, '+');
  };

  var queryString = {
    'timestamp': timestamp
  };

  var result = fetch('server.php', {
    method: 'post',
    headers: {
      "Content-type": "application/x-www-form-urlencoded"
    },
    body: toQueryString(queryString)
  })

  result.then(function(response) {
    return response.json()
  }).then(function(text) {
    document.querySelector('#response').innerHTML = text.data_from_file;
    getContent(text.timestamp);
  })['catch'](function(ex) {
    getContent(timestamp);
  })
}

javaQest 11.08.2015 13:23

Цитата:

Сообщение от KosBeg
json_encode($data), json_decode($data)

это вряд ли парсеры, парсер -- это библиотека для разбора. То что ты нашел, это скорей всего енкодер и декодер.

Erolast 11.08.2015 17:19

Цитата:

не проще, я просто не могу понять как его принять на сервере)
https://www.google.com/search?q=php+recieve+json
$data = json_decode(file_get_contents('php://input'), true);


Цитата:

Мне честно говоря, читать твой код -- серпом по яйцам. Переписал бы ты его традиционным синтаксисом.
Ну, вообще-то, то, что ты не можешь прочитать вполне валидный и стандартный код, уже само по себе означает, что языка ты не знаешь. Ну да ладно, пойду на встречу - http://javascript.ru/forum/showthread.php?p=383662.

KosBeg 11.08.2015 17:33

Цитата:

Сообщение от Erolast
https://www.google.com/search?q=php+receive+json
$data = json_decode(file_get_contents('php://input'), true);

спасибо, потом попробую)

javaQest 11.08.2015 17:33

Erolast,
с ходу возникла непонятка
subClass.prototype = Object.create(superClass && superClass.prototype,

ты почему тут перезаписываешь прототип сабклассу? если сабкласс наследует что-то у суперкласса, это не значит что он должен забыть о себе. Или я что-то не так понял?

KosBeg 11.08.2015 17:37

Erolast,
http://stackoverflow.com/questions/1...-post-with-php =>
Цитата:

Please forget my bad english.
это ты вопрос задавал? :lol:

javaQest 11.08.2015 17:45

Erolast,
и вот еще непонятка.
я глянул в описании setPrototypeOf, судя по этому вот полифилу
Object.setPrototypeOf = Object.setPrototypeOf || function(obj, proto) {
  obj.__proto__ = proto;
  return obj; 
}

в качестве аргументов там объекты(настоящие), а у тебя
if (superClass) {
        Object.setPrototypeOf(subClass, superClass);
    }

функции (а-ля "классы"). Как это понимать?

Erolast 11.08.2015 17:45

Цитата:

ты почему тут перезаписываешь прототип сабклассу?
Подразумевается, что функция inherits будет применяться сразу после объявления класса, до установки методов в прототип, пока он еще чистый - тогда ничего не перезапишется. Можно заменить на более простое
Object.setPrototypeOf(subClass.prototype, superClass && superClass.prototype);

В контексте организации множественного наследования ничего не изменится.

Erolast 11.08.2015 17:47

Цитата:

в качестве аргументов там объекты(настоящие), а у тебя
[js]
if (superClass) {
Object.setPrototypeOf(subClass, superClass);
}
[js]
функции (а-ля "классы"). Как это понимать?
Что не так? Функции (классы) в JS - те же настоящие объекты, и у них тоже есть прототип (который [[Prototype]]).
Object.setPrototypeOf - это то же, что и установка __proto__, только по стандарту ES6.

И давай лучше в той теме общаться, здесь это оффтоп как-то.

javaQest 11.08.2015 17:48

Цитата:

Сообщение от Erolast
В контексте организации множественного наследования ничего не изменится.

Нет, так не годится. Допустим, у меня есть класс, который уже содержит в своем прототипе foo. я наследую, и теряю это foo, при таком раскладе. Это детский сад

Erolast 11.08.2015 17:49

Цитата:

Сообщение от KosBeg (Сообщение 383671)
Erolast,
http://stackoverflow.com/questions/1...-post-with-php =>
это ты вопрос задавал? :lol:

С чего ты взял?

javaQest 11.08.2015 17:49

Erolast,
хорошо, ответ на этот пост читай в той теме

KosBeg 11.08.2015 17:50

Цитата:

Сообщение от Erolast
С чего ты взял?

не понимаешь ты шуток)
надо "receive", а у тебя "recieve", может опечатка

Erolast 11.08.2015 17:50

Цитата:

Сообщение от javaQest (Сообщение 383678)
Нет, так не годится. Допустим, у меня есть класс, который уже содержит в своем прототипе foo. я наследую, и теряю это foo, при таком раскладе. Это детский сад

Ты хочешь наследовать в рантайме? Окей, поправил.
Просто я ж с ES6 переписывал, а там наследование устанавливается в момент объявления класса.


Часовой пояс GMT +3, время: 06:32.