等待JS异步功能完成,然后再运行一些同步代码

时间:2020-08-12 18:01:51

标签: javascript asynchronous promise jquery-deferred deferred

我有一个异步函数getDataItem,该函数返回一个promise并将数据传递给另一个函数preparePhysicianSchemaData,该函数从传递的数据以及调用后获取的数据中构建全局对象physicianDetailsObj对于最初传递的每一行数据,它内部还有一个异步函数。

getDataItem(listID, itemID).then(preparePhysicianSchemaData)

仅在完全填充全局对象变量physicianDetailsObj之后,才需要调用另一个名为buildSEOSchemaBlock()的函数,该函数的作用是解析physicianDetailsObj对象并构建所需的最终对象。

我宁愿不使用setTimeOut尝试计时:

      setTimeout(function(){ return getListItem(listID, itemID).then(preparePhysicianSchemaData) }, 10);
      setTimeout(function(){ return buildPhysicianSchemaBlock() }, 3000); 

我如何像这样链接最后一个函数:getDataItem(listID, itemID).then(preparePhysicianSchemaData).then(buildPhysicianSchemaBlock)确保仅在完全填充全局对象变量physicianDetailsObj之后运行最后一个函数?

    var physicianDetailsObj = {};
    function getListItem() {}  //returns promise
    function preparePhysicianSchemaData(item) {
        var tempPhysicianDetailsObj = {};   
        var currentPhysicianItemId = item.get_id();
    
        tempPhysicianDetailsObj = {
            "name" : item.get_item("Title"),
            "url" : item.get_item("SEOCanonicalHref").match('href="([^"]+)')[1]
        };
     
         var currentItemPhysicianTag= item.get_item("PhysicianItemTag").get_label();  
    
         getPhysicianLocationDetailsFromServiceLocations(currentItemPhysicianTag).then(function(slitems) {
            console.log(slitems);
            var slitemEnum = slitems.getEnumerator();
    
            //first empty the object
            Object.keys(physicianDetailsObj).forEach(k => delete physicianDetailsObj[k]);
    
            while (slitemEnum.moveNext()) {
                var slitem = slitemEnum.get_current();
                physicianDetailsObj[currentPhysicianItemId + '-' + slitem.get_id()] = {
                    "name":  tempPhysicianDetailsObj["name"],
                    "image": tempPhysicianDetailsObj["image"],
                    "url": tempPhysicianDetailsObj["url"],
                    "streetAddress": slitem.get_item("LocationAddress"),
                    "addressLocality": slitem.get_item("LocationLU_x003A_LocationCity").get_lookupValue()
                }
            }
         }); 
    
    }

function buildSEOSchemaBlock(){ }  //process physicianDetailsObj

getPhysicianLocationDetailsFromServiceLocations是一个异步函数,在preparePhysicianSchemaData

内部被调用

2 个答案:

答案 0 :(得分:1)

如果preparePhysicianSchemaData是同步的,则不需要等待它,只需在它之后执行操作即可。像这样:

getListItem(listID, itemID).then(function() {
  preparePhysicianSchemaData();
  buildPhysicianSchemaBlock();
});

或者如果您需要Promise的结果,例如:

getListItem(listID, itemID).then(function(result) {
  preparePhysicianSchemaData(result);
  buildPhysicianSchemaBlock();
});

如果它是异步,则可以链接Promises,类似于:

getListItem(listID, itemID)
  .then(function(result) { return preparePhysicianSchemaData(result); })
  .then(function(newResult) { return buildPhysicianSchemaBlock(newResult); });

基本上,每次对.then()的调用都会将先前Promise的结果传递给新的异步函数,并返回该函数的Promise。

答案 1 :(得分:1)

如果您需要严格按照顺序执行功能,请使用async / await和Promises,看看此演示

// Use async
(async () => {
  // Function 1
  const fn1 = (val) => {
    return new Promise((resolve, reject) => {
      // Do some stuff here
      val = val + 1;
      // Resolve result.
      // Can be resolved from any level
      // of nested function!
      function nested1() {
        function nested2() {
          resolve(val);
        }
        nested2();
      }
      nested1();
    });
  };
  
  // Function 2
  const fn2 = (val) => {
    return new Promise((resolve, reject) => {
      // Do some stuff here
      val = val * 2;
      // Resolve result
      resolve(val);
    });
  };
  
  // Function 3
  const fn3 = (val) => {
    return new Promise((resolve, reject) => {
      // Do some stuff here
      val = val + 1000;
      // Resolve result
      resolve(val);
    });
  };
  
  // Async code
  let val = 5;
  
  val = await fn1(val); // Wait until fn1 resolves
  val = await fn2(val); // Wait until fn2 resolves
  val = await fn3(val); // Wait until fn3 resolves
  
  console.log(val);
})();