在 运行 一些同步代码之前等待 JS 异步函数完成

waiting for JS async func to complete before running some sync code

我有一个异步函数 getDataItem,它 returns 承诺并将数据传递给另一个函数 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

内部调用的异步函数

如果preparePhysicianSchemaData是同步的那么你就不需要等待它,只需要执行它之后的操作。像这样:

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

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

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

如果它是 异步的 那么你可以链接 Promise,比如:

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

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

如果你需要一个接一个地严格执行函数,使用async/await和Promises,看看这个demo

// 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);
})();