如何使用 promises 在 JS 中实现自定义 'confirm' 提示符

How to implement a custom 'confirm' prompt in JS using promises

这是基本代码

$(".add-item").click(function() {
  var flag;
  var ask_about_flag = // some logic ... 
  if (ask_about_flag == true) {
    if (confirm("Add with a flag?") == true) {
      flag = true
    } else {
      flag = false
    }
  } 
  addItem(flag)
})

不过,我想做的是构建一个强大的模式,其中包含有关如何回答所提出的 'Add with a flag?' 问题的具体说明。在模式中,'Yes' 与 'No' 将有 2 个按钮元素。因此,将其视为基本模态(使用 Bootstrap):

<div class="modal fade" tabindex="-1" role="dialog" aria-labelledby="flag_modal" aria-hidden="true" id="flag_modal">
    <div class="modal-dialog modal-lg" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h2 class="modal-title serif text-center">
            Add with a flag?
          </h2>
        </div>
        <div class="modal-body">
          <!-- detailed instructions -->
          <button id="yes" class="btn btn-lg">Yes</button>
          <button id="no" class="btn btn-lg">No</button>
        </div>
      </div>
    </div>
</div>

和默认的confirm alert一样,UX是当add-item被点击时,如果不包含的逻辑计算出ask_about_flag为真,就会弹出这个modal,并且在用户选择 #yes#no 来设置标志的值之前,代码不会继续调用 addItem

然而,也有可能在点击 add-item 时,未包含的逻辑计算出 ask_about_flag 为假,因此模态框不显示并调用 addItem ( flag = null 在这种情况下)。

因此,我认为代码组织将 addItem 函数调用保留在 add-item 单击中而不是将其下推到按钮处理程序中是有意义的(下面的代码很清楚会工作)

$(".add-item").click(function() {
  var ask_about_flag = // some logic ... 
  if (ask_about_flag == true) {
    $("#flag_modal").show()
  } 
  addItem()
})

$("#yes").click(function() {
  addItem(true)
})

$("#no").click(function() {
  addItem(false)
})

我想做一些事情,例如:

$(".add-item").click(function() {
  var flag;
  var ask_about_flag = // some logic ... 
  if (ask_about_flag == true) {
    // pop up modal to ask user to set value of flag
  } 
  // wait to execute until value of flag is set, if needed
  addItem(flag)
})

似乎 Promises 是正确的方法(如果不是,请告诉我!),但这对我来说仍然很新,所以我试了一下下面的方法。一直工作到我单击 yesno 按钮时我得到 Uncaught TypeError: promise.resolve is not a function

var promise; // declare so that it's available both from within `add-item` and `button` handlers

$(".add-item").click(function() {
  promise = new Promise(function(resolve, reject) { 
    var ask_about_flag = // some logic ... 
    if (ask_about_flag == true) {
      $("#flag_modal").modal("show")
    } else {
      resolve(null)
    }
  })

  promise.then(function(flag) {
    // flag is the parameter passed to resolve
    addItem(flag)
  })
})

$("#yes").click(function() {
  promise.resolve(true)
})

$("#no").click(function() {
  promise.resolve(false)
})

FIDDLE: https://jsfiddle.net/0g76ce5s/

实际上,我更喜欢你的第一种方法,因为它更关注分离。

但是如果你想做 Promise 方法,你需要传递的是 resolve 函数而不是 Promise。

示例如下:

var resolveGlobal; // declare so that it's available both from within `add-item` and `button` handlers

$(".add-item").click(function () {
    promise = new Promise(function (resolve, reject) {
        var ask_about_flag = true;
        if (ask_about_flag) {
            $("#flag_modal").modal("show");
            resolveGlobal = resolve;
        } else {
            resolve(null);
        }
    });

    promise.then(function (flag) {
        // flag is the parameter passed to resolve
        addItem(flag);
    });
});

$("#yes").click(function () {
    resolveGlobal(true);
});

$("#no").click(function () {
    resolveGlobal(false);
});

function addItem(flag) {
    console.log(flag);
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script
            src="https://code.jquery.com/jquery-3.6.0.min.js"
            integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
            crossorigin="anonymous"
        ></script>
        <link
            rel="stylesheet"
            href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
            crossorigin="anonymous"
        />
        <script
            src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
            integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
            crossorigin="anonymous"
        ></script>
        <script
            src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
            integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
            crossorigin="anonymous"
        ></script>
        <script
            src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
            integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
            crossorigin="anonymous"
        ></script>
    </head>
    <body>
        <div id="box">
            <div
                class="modal fade"
                tabindex="-1"
                role="dialog"
                aria-labelledby="flag_modal"
                aria-hidden="true"
                id="flag_modal"
            >
                <div class="modal-dialog modal-lg" role="document">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h2 class="modal-title serif text-center">
                                Add with a flag?
                            </h2>
                        </div>
                        <div class="modal-body">
                            <!-- detailed instructions -->
                            <button id="yes" class="btn btn-lg">Yes</button>
                            <button id="no" class="btn btn-lg">No</button>
                        </div>
                    </div>
                </div>
            </div>

            <button class="add-item">Add item</button>
        </div>
    </body>
</html>