1

Описание

После небольшой дискуссии решил создать собственную версию window.prompt(). Моя версия выглядит так:

class Manager {
  static async prompt(message) {
    const dialog = document.body.appendChild(document.createElement(`dialog`));
    dialog.appendChild(document.createElement(`span`)).innerText = message;
    const input = dialog.appendChild(document.createElement(`input`));
    input.type = `text`;
    const promise = new Promise((resolve) => {
      dialog.addEventListener(`click`, (event) => {
        if (event.target == dialog) {
          resolve(input.value);
          dialog.remove()
        }
      });
    });
    dialog.showModal();
    return await promise;
  }
}

document.write(Manager.prompt(Input text));

* {
  margin: 0;
  padding: 0;
  border: none;
  outline: none;
}

body {
  background-color: rgb(25, 25, 25);
  color: rgb(255, 255, 255);
}

body * {
  background-color: inherit;
  color: inherit;
  border-radius: 8px;
}

dialog {
  background-color: rgb(50, 50, 50);
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: auto;
  padding: 8px;
}

input {
  background-color: rgb(25, 25, 25);
  padding: 8px;
}

dialog::backdrop {
  background-color: rgba(0, 0, 0, 50%)
}

После ввода надо нажимать вне окна и значение передается. Проблема в том, что, чтобы я не делал, где бы я не пимал async и await передается Promise<String>.

Вопрос

Но что мне делать, чтобы передавалась просто String, как во встроенной версии.

Уточнение

Возможно проблема в том, что я неправильно реализовал async и await, поскольку немного работал с ними и не все тонкости знаю. Так что с удовольствием приму и статью где, есть решение моей проблемы и объяснения - почему так происходит.

eccs0103
  • 2,979
  • Зачем вам тут аснхронность? Я не вижу ничего что требует асинхронности тут – EzioMercer Jan 02 '23 at 14:42
  • @EzioMercer ну так значение возвращается не сразу, а когда пользователь нажмет вне окна. Можете показать правильное решение без асинхронности? – eccs0103 Jan 02 '23 at 14:47
  • Ну не то чтобы без асинхронности, но вам просто надо навестить правильно слушателей, которые сами по себе асинхронны (я уже говорил вам об этом). Вам не нужно самому прописывать асинхронность – EzioMercer Jan 02 '23 at 14:49
  • @EzioMercer вот в этом и проблема. Думаю, я не совсем понимаю как работает асинхронность и искал по поводу этого примеры в интернете. Из 5 страниц Google только примеры как сериализовать асинхронность с fetch, с новой Promise и.т.д., но нигде нет ни один единственный случай с нажатием кнопки или какого-то другого обработчика. – eccs0103 Jan 02 '23 at 14:54
  • Надо не по гуглу искать, а надо в доках прочитать :) Извините, но это не маленькая тема, чтобы тут расписывать подробно – EzioMercer Jan 02 '23 at 15:05
  • @Grundy ответ к которому вы оставили ссылку, не решает этот вопрос. В данном вопросе я именно таким способом и пытаюсь решить и не получается. К тому же в вашем вопросе используется ajax, jquery и.т.д., а тут библиотеки не используются. Так что вопрос не дубликат. – eccs0103 Jan 02 '23 at 16:15
  • На самом деле неважно что вы используете библиотеку или fetch, в указанном @Grundy дубликате, в ответах достатоточно подробно описано, почему нельзя работать с асинхронными функциями т.к. хотите вы. И там даны множество обходных путей. Так что вопрос как по мне закрыт правильным дубликатом – EzioMercer Jan 02 '23 at 16:35
  • @eccs0103, решает, достаточно добавить await и получишь нужно значение, о чем и указано в дубликате. – Grundy Jan 02 '23 at 17:36

1 Answers1

0

Можно вашу задачу решить простым колбеком, чтобы не мучаться с асинхронностью:

class Manager {
  static prompt(message, callBack) {
    const dialog = document.createElement('dialog');
    const span = document.createElement('span');
    const input = document.createElement('input');
span.innerText = message;
input.type = 'text';

dialog.addEventListener('click', (event) =&gt; {
  if (event.target !== dialog) return;

  callBack(input.value);
  dialog.remove();
});

dialog.append(span, input);
document.body.append(dialog);

dialog.showModal();

} }

Manager.prompt('Input text', (ans) => document.write(ans));

* {
  margin: 0;
  padding: 0;
  border: none;
  outline: none;
}

body {
  //background-color: rgb(25, 25, 25);
  //color: rgb(255, 255, 255);
}

body * {
  background-color: inherit;
  color: inherit;
  border-radius: 8px;
}

dialog {
  background-color: rgb(50, 50, 50);
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: auto;
  padding: 8px;
}

input {
  background-color: rgb(25, 25, 25);
  padding: 8px;
}

dialog::backdrop {
  background-color: rgba(0, 0, 0, 50%)
}

Как только вы начнёте писать async и/или использовать Promise-ы, там надо будет всё это дело вызывать в асинхронной функции или использовать синтаксис then. Про подробное объяснение, почему без этого нельзя обойтись, можете почитать мой ответ

EzioMercer
  • 6,178
  • 2
  • 9
  • 28
  • Я и использовал в проекте тот метод который вы описали выше. Вопрос о другом. Это попытка создать точь в точь prompt() исправляя ее недостатки, а не обойти их. – eccs0103 Jan 02 '23 at 16:19
  • @eccs0103, не получится так. Как только вы начнёте писать async и/или использовать Promise-ы, там надо будет всё это дело вызывать в асинхронной функции или использовать синтаксис then. Про подробное объяснение, почему без этого нельзя обойтись, можете почитать мой ответ – EzioMercer Jan 02 '23 at 16:29
  • 1
    О том, что после async придётся обязательно использовать await еще и снаружи я и не имел понятия, так как мой второй рабочий язык является C# и там эта конструкция прекрасно работает. Вот я и думал, что не смотря различия этих языков они и не редко похожи, поэтому и тут должно работать. Ваш комментарий дополняет ответ. Вставьте его в ответ и я приму его. – eccs0103 Jan 02 '23 at 16:46
  • @eccs0103, в c# ты точно также не можешь получить значение без await – Grundy Jan 02 '23 at 17:41
  • @Grundy я не говорю без await, я буду использовать await внутри функции и она вернет не Task<String>, а String как указано в примере. – eccs0103 Jan 02 '23 at 18:18
  • @Grundy а в JS async функция вернет с await или без, все равно получаешь Promise<...> – eccs0103 Jan 02 '23 at 18:20
  • @eccs0103, точно также как и в c# - тут у них нет никакой разницы. – Grundy Jan 02 '23 at 18:30
  • @Grundy проверил примером - вы правы! Чёт я запутался. :) А тогда как работает window.prompt() который является асинхронной функцией, но возвращает не Promise? – eccs0103 Jan 02 '23 at 18:42
  • @eccs0103 А кто сказал, что window.promt() - асинхронный? – EzioMercer Jan 02 '23 at 18:46
  • @eccs0103, браузерный prompt - это синхронная функция, которая блокирует выполнение всех скриптов, во время своего выполнения – Grundy Jan 02 '23 at 18:47
  • 1
    EzioMercer, @Grundy понял, благодарю за объяснения (и терпение :) ) . – eccs0103 Jan 02 '23 at 18:51