JS - Return 空承诺,稍后解决

JS - Return empty promise and resolve it later

在 JS 中,我想:

  1. 定义一个定义承诺的函数。
  2. 此函数然后有一个事件来解决承诺。
  3. 函数returns尚未解决的承诺。
  4. 当 promise 被 resolve 时,调用者将收到 resolve 的值。

像这样:

function my_func() {
    // This creates an empty promise.
    const p = Promise;

    // When a user clicks a button in UI then we resolve the promise.
    // This would be in an event!
    // p.resolve('user clicked OK');

    // Returns empty promise.
    return p;
}

function main() {
    // Here when the promise is resolved then we get the value.
    my_func().then(function(v) {
        console.log(v);
    });
}

这似乎是一个奇怪的设计,但正如 Bergi 评论的那样,没有什么能阻止你这样做 -

function my_func () {
  return new Promise(r =>
    document.forms.myapp.mybutton.onclick = r
  )
}

function main () {
  my_func().then(event => console.log(event.target))
}

main()
<form id="myapp">
  <button type="button" name="mybutton">Click me</button>
</form>

一个 Promise 最多可以解析 一次 次,因此在第一次点击后自动删除事件侦听器可能是有意义的。我们可以将 my_func 重命名为 onclick 并为其提供一个参数以使其可重用 -

function onclick(elem) {
  return new Promise(r =>
    elem.addEventListener("click", r, {once: true})
  )
}

function main () {
  onclick(document.forms.myapp.mybutton)
    .then(event => console.log(event.target))
    
  onclick(document.forms.myapp.otherbutton)
    .then(event => console.log(event.target))
}

main()
<form id="myapp">
  <button type="button" name="mybutton">A</button>
  <button type="button" name="otherbutton">B</button>
</form>

现在 onclick 可以以更有趣的方式使用。例如,我们可以制作一个需要 两次 点击才能触发效果的按钮 -

function onclick(elem) {
  return new Promise(r =>
    elem.addEventListener("click", r, {once: true})
  )
}

function main () {
  onclick(document.forms.myapp.mybutton)
    .then(event => console.log(event.target))
    
  onclick(document.forms.myapp.otherbutton)
    .then(_ =>
      onclick(document.forms.myapp.otherbutton)
        .then(event => console.log(event.target))
    )
}

main()
<form id="myapp">
  <button type="button" name="mybutton">click once</button>
  <button type="button" name="otherbutton">click twice</button>
</form>

在这里找到答案:

deferreds 可以随意传递,然后可以在其他地方解决或拒绝承诺。
还没有在代码中测试这个,所以不知道这个方法是否有任何问题。

function my_func() {
  const deferreds = [];
  const p = new Promise(function (resolve, reject) {
    deferreds.push({ resolve: resolve, reject: reject });
  });
  const btn = document.querySelector('.btn');

  btn.addEventListener('click', event => {
    deferreds[0].resolve('User clicked button!');
  }, {once: true});

  return p;
}

function main() {
  my_func().then(function (v) {
    console.log(v);
  });
}

main();
<button class="btn">
    Hi! Click me
</button>