为什么在函数结束执行之前发送我的诺言的“解决”?

时间:2019-07-18 18:57:07

标签: javascript asynchronous promise

我有一个函数(内部包含promise,因此它本身可以同步运行)似乎在我的主代码中异步运行。无论我如何格式化我的诺言,似乎在函数结束执行之前就已发送解决方法:

这个问题在逻辑上也是递归的,因为如果我尝试在nameExists函数周围添加另一个promise(在这个promise之内),然后将解决方案放在“ then”中,那么我只会遇到嵌套的解决方案...

    document.getElementById("config-select").addEventListener("input", function(){
      //check if the doc name exists: returns doc id
      //promise that doc_obj is created before moving on
      let doc_obj = {};
      let promise = new Promise(function (resolve, reject) {
        let doc_name = document.getElementById("config-select").value;
        doc_obj = nameExists(doc_name);
        resolve('done'); //this executes BEFORE nameExists is done processing...bringing back the original asynch issue i was trying to fix in the first place...
      });
      promise.then(function (result) {
          alert("then: "+doc_obj);
          if(doc_obj.bool === true){//it does exist:
            alert("replacing id");
            document.getElementById("config-select").setAttribute("doc-id", doc_obj.id);
          }
          else{//it doesn't:
            alert("resetting id");
            document.getElementById("config-select").setAttribute("doc-id", "");
          }
        }
      );

    });

nameExists函数:

//check if the name in config-select is an existing doc (assumes name is a unique document field)
const nameExists = function(name){
  //get all docs
  localDB.allDocs({include_docs: true}).then(function (result) {
    //return object set to default state if no match is found
    let doc_obj = {bool: false, id: ""};
    alert("Entering the match checker...");

    for(let i =0; i<result.total_rows; i++) {
      if(result.rows[i].doc.name == name){
        alert(result.rows[i].doc.name);
        alert(name);
        doc_obj.bool = true;
        doc_obj.id = result.rows[i].doc._id;
        //found a match
        break;
      }
    }
    //return the result
    alert("returned obj.id: "+doc_obj.bool);
    return doc_obj;

  }).catch(function (err) {console.log(err);});
};

理想情况下,在评估“ if语句”之前,我希望使用nameExists函数中的数据填充doc_obj或某些返回值对象。我该如何格式化我的promise / resolve语句来实现这一目标?

2 个答案:

答案 0 :(得分:1)

您应该删除该new Promise-它不会改变您是否能够等待nameExists的结果。您将需要returnthen()函数内部创建的承诺:

nameExists

然后,您可以在事件监听器中等待它:

function nameExists(name) {
  return localDB.allDocs({include_docs: true}).then(function (result) {
//^^^^^^
    for (let i =0; i<result.total_rows; i++) {
      if (result.rows[i].doc.name == name){
        return {bool: true, id: result.rows[i].doc._id};
      }
    }
    return {bool: false, id: ""};
  });
//  ^ don't catch errors here if you cannot handle them and provide a fallback result
}

答案 1 :(得分:0)

您仅有的一个异步调用位于nameExists函数内部,该函数是数据库调用,因此无需编写两个Promise,只需一个Promise就可以解决您的问题。

第一个事件应该是这样的:

document.getElementById("config-select").addEventListener("input", function(){
   nameExists(doc_name).then(function(doc_obj) {
       alert("then: "+doc_obj);
       if(doc_obj.bool === true){//it does exist:
          alert("replacing id");
          document.getElementById("config-select").setAttribute("doc-id",  doc_obj.id);
       }
       else{//it doesn't:
          alert("resetting id");
          document.getElementById("config-select").setAttribute("doc-id", "");
       }
   }).catch(function (err) { console.log(err) });
});

和nameExists函数应如下所示:

//check if the name in config-select is an existing doc (assumes name is a unique document field)
const nameExists = function(name){
  //get all docs
  return localDB.allDocs({include_docs: true}).then(function (result) {
    //return object set to default state if no match is found
    let doc_obj = {bool: false, id: ""};
    alert("Entering the match checker...");

    for(let i =0; i<result.total_rows; i++) {
      if(result.rows[i].doc.name == name){
        alert(result.rows[i].doc.name);
        alert(name);
        doc_obj.bool = true;
        doc_obj.id = result.rows[i].doc._id;
        //found a match
        break;
      }
    }
    //return the result
    alert("returned obj.id: "+doc_obj.bool);
    return(doc_obj); // here is where the code runs then statement inside the event

 });      
};