简体   繁体   English

如何避免 javascript 中的异步功能?

[英]How to avoid async functions in javascript?

function CanPurchase() {
return new Promise(function(resolve, reject){
  var name = document.getElementById('name').value;
      var civilNumber = document.getElementById('civilNumber').value;

      var canPurchase_query = db.collection("observer").doc("purchase_record").collection("record_set").where("name",
        "==", name).where("civilNumber", "==", civilNumber);
      var result = "";

     canPurchase_query
        .get()
        .then(function (querySnapshot) {
          querySnapshot.forEach(function (doc) {
            // doc.data() is never undefined for query doc snapshots
            result += doc.data().time;
          });
          if (result) {
            console.log("canPurchase", false);
            alert(false);
            resolve(false);
          } else {
            alert(true);
            console.log("canPurchase", true);
            resolve(true);
          }
        })
        .catch(function (error) {
          alert(false);
          console.log("Error getting documents: ", error);
          resolve(false);
        });


});

    }

function StoreBuyerListInDB() {
      var serialNumber = document.getElementById("serialNumber3").value;
      var name = document.getElementById("name").value;
      var count = document.getElementById("count3").value;
      var civilNumber = document.getElementById("civilNumber").value;
      var canPurchase = CanPurchase().then(function(resolvedData){
        return resolvedData;
      });
      sleep(3222);
      //DB에 시리얼넘버, 이름, 개수, 주민번호 넣기
      var docRef = db.collection("users").doc(firebaseEmailAuth.currentUser.uid);
      var docRef2 = db.collection("users").doc(firebaseEmailAuth.currentUser.uid).collection("buyers");
      var docRef3 = db.collection("observer").doc("purchase_record").collection("record_set");
      //로그인된 사용자가 seller인지 확인
      docRef.get().then(function (doc) {
        if (doc.exists) {
          if (doc.data().index != "seller") {
            alert('seller가 아니라면 등록할 수 없습니다! 돌아가세요!');
            return;
          }
          console.log("Document data:", doc.data());
        } else {
          // doc.data() will be undefined in this case
          console.log("No such document!");
          return;
        }
      }).catch(function (error) {
        console.log("Error getting document:", error);
      });

      //어느 칸이라도 비어있으면 안됨
      if (!serialNumber || !name || !count || !civilNumber) {
        alert('제대로 입력해주세요!');
        return;
      }
      //갯수가 0개이상 3개이해
      else if (count < 0 || count >= 3) {
        alert('1인당 3개 이하의 마스크만 구매 가능합니다! 다시 입력해주세요!');
        return;
      }
      //주민번호 유효성
      else if (!ValidateCivilNumber(civilNumber)) {
        alert('주민번호가 유효하지 않습니다.');
        return;
      }
      //전체 구매자 db에 이름, 주민번호가 같은사람이 있을경우 등록 불가
      else if (!canPurchase) {
        alert('이번주에 이미 구매하셨습니다.');
        return;
      }
      else{
        //해당seller의 db에 저장
        docRef2.add({
            name: name,
            serialNumber: serialNumber,
            count: count,
            civilNumber: civilNumber,
            time: firebase.firestore.FieldValue.serverTimestamp()
          })
          .then(function (docRef) {
            console.log("Document written with ID: ", docRef.id);
            alert("seller 저장 완료!");
            setTimeout(GetDataFromDB(), 3000);
          })
          .catch(function (error) {
            console.error("Error adding document: ", error);
            alert("seller 저장 실패!");
          });
        //감사자인 observer db에 저장
        docRef3.add({
            name: name,
            serialNumber: serialNumber,
            count: count,
            civilNumber: civilNumber,
            time: firebase.firestore.FieldValue.serverTimestamp()
          })
          .then(function (docRef) {
            console.log("Document written with ID: ", docRef.id);
            alert("observer 저장 완료!");
            setTimeout(GetDataFromDB(), 3000);
          })
          .catch(function (error) {
            console.error("Error adding document: ", error);
            alert("observer 저장 실패!");
          });
        }
    }

I wanna know user can purchase items or not by using CanPurchase() function and if process.我想知道用户可以通过使用 CanPurchase() function 和 if 过程来购买物品。 But in real case, it doesn't work.但在实际情况下,它不起作用。

 else if (!canPurchase) {
        alert('이번주에 이미 구매하셨습니다.');
        return;
      }

here it just pass this logic.在这里它只是通过这个逻辑。 so whatever canPurchase variable is, it just go on.所以无论 canPurchase 变量是什么,它只是 go 。 So I searched some ways to avoid this problem.所以我搜索了一些方法来避免这个问题。 I used promise.我用的是 promise。 but also it doesn't work too.但它也不起作用。 How can i solve it?我该如何解决? Thank you so much !!太感谢了 !!

There is no way to make code that calls an asynchronous API behave synchronously.无法使调用异步 API 的代码同步运行。 If you want to interact with cloud-based (and most other modern) APIs, you will have to learn to work with asynchronous calls.如果您想与基于云的(以及大多数其他现代)API 进行交互,则必须学习使用异步调用。

In your case, the code for CanPurchase can be a bit simpler, as you don't need to declare your own promise as far as I can see.在您的情况下, CanPurchase的代码可能会更简单一些,因为据我所知,您不需要声明自己的 promise 。 It should be something like this:它应该是这样的:

function CanPurchase() {
  var name = document.getElementById('name').value;
  var civilNumber = document.getElementById('civilNumber').value;

  var canPurchase_query = db.collection("observer").doc("purchase_record")
    .collection("record_set")
    .where("name", "==", name)
    .where("civilNumber", "==", civilNumber);
  var result = "";

  return canPurchase_query
    .get()
    .then(function (querySnapshot) {
      querySnapshot.forEach(function (doc) {
        result += doc.data().time;
      });
      return !result
    })
    .catch(function (error) {
      return false;
    });
});

So this no longer has a custom Promise , but instead returns the value from within then and catch and then the query.因此,这不再具有自定义Promise ,而是从 then 内部返回值, then catch和查询。 This is a common pattern when using promises, and is called bubbling up the results.这是使用 Promise 时的常见模式,称为冒泡结果。

You can now call this function with:您现在可以使用以下命令调用此 function:

canPurchase().then(function(result) {
  if(!result) {
    alert('이번주에 이미 구매하셨습니다.');
  }
}

If you're OK with using some more modern JavaScript feature, you can use async / await to make this code look a bit more familiar:如果您可以使用一些更现代的 JavaScript 功能,您可以使用async / await使这段代码看起来更熟悉一些:

async function CanPurchase() {
  ...
}

let result = await canPurchase();
if(!result) {
  alert('이번주에 이미 구매하셨습니다.');
}

Just keep in mind that this is syntactic sugar around the existing flow with promises, and does not change the fact that these are asynchronous calls.请记住,这是围绕带有承诺的现有流程的语法糖,并且不会改变这些是异步调用的事实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM