如何让我的函数在返回另一个调用之前等待

时间:2019-07-05 10:23:12

标签: javascript apex

我有一项返回一些翻译的服务。它发出本质上是异步的顶点调用并返回翻译。每次获得一组结果时,我都会将翻译内容存储在会话存储中,而下次调用时,我会先在缓存的翻译内容中进行检查,如果可用,我会返回。当用户为同一组值发送多个翻译请求时,就会出现问题。为此,我一直在跟踪顶点调用。但是我不确定如何使我的请求等待上一个顶点调用结束并返回结果。

这是服务代码。

let labelQueue = [];
let labelMap;
let requestCustomLabels = function(labelsArr, language) {
  return new Promise(function(resolve, reject) {
    let labelsArray = [...labelsArr];
    let returnedLabels = {};
    let cachedLabels = JSON.parse(sessionStorage.getItem("customLabels")) || {};
    labelMap = { ...cachedLabels };
    if (Object.keys(labelMap).length > 0) {
      labelsArray.forEach(item => {
        if (Object.keys(labelMap).indexOf(item) > -1) {
          labelsArray = labelsArray.filter(label => label !== item);
          //push the available lables inside returnedLabels
          returnedLabels[item] = labelMap[item];
        }
      });
    }
    if (Object.keys(returnedLabels).length === labelsArr.length) {
      resolve(returnedLabels);
    }
    if (labelQueue.length && labelsArray.length) {
      labelsArray.forEach(item => {
        if (labelQueue.indexOf(item) > -1) {
          labelsArray = labelsArray.filter(label => label !== item);
        }
      });
    }
    if (labelsArray.length) {
      // store labels to the queue
      labelsArray.forEach(label => {
        labelQueue.push(label);
      });
      // then make call to apex for the result and store it inside returnedLabels & localmap and remove them from labelsQueue
      fetchLabels(labelsArray, returnedLabels, language).then(
        labelsReturned => {
          returnedLabels = { ...returnedLabels, ...labelsReturned };
          resolve(returnedLabels);
        }
      );
    } else {
      // wait for apex to return the call;
    }
  });
};

let fetchLabels = function(labelsArray, returnedLabels, language) {
  return new Promise(function(resolve, reject) {
    getUserProfile().then(function(userData) {
      language = language || userData.language;
      getCustomLabel(labelsArray, language)
        .then(res => {
          let labels = JSON.parse(res).data;
          for (const key in labels) {
            if (key !== "language" && key !== "totalSize") {
              //when the apex call returns remove the labels from the label Queue.
              labelQueue = labelQueue.filter(label => label !== key);
              returnedLabels[key] = labels[key];
              labelMap[key] = labels[key];
            }
          }
          // store localsMap to the storage
          sessionStorage.setItem("customLabels", JSON.stringify(labelMap));
          resolve(returnedLabels);
        })
        .catch(function(error) {
          console.error("error : ", error);
          reject(error);
        });
    });
  });
};

1 个答案:

答案 0 :(得分:0)

我实际上编写了此脚本,主要用于获取在影子dom应用程序中从页面上的多个元素调用的语言文件。

您需要:

  1. 检查诺言是否已存储。
  2. 将ajax承诺另存为变量。
  3. 存储变量(如果未存储)。
  4. 获取承诺,或返回存储的承诺。
  5. 兑现承诺。

    var ajaxQueue = {};
    
    /**
    * @description Avoids unnecessary calls to server
    * @param {String} url The api call
    * @param {String} method 'GET', 'POST', 'PUT', 'DELETE'
    * @param {String} data If sending data through POST/PUT
    */
    function queueAJAXCalls(url, method, data) {
      var property = FXAjaxBehavior.getQueueProperty(url, method);
    
      if (firstTimeRequesting(property)) {        // 1
        var ajaxPromise = someGeneralCodeForFetchingAjaxData(url, method, data)  // 2
        .then(function(serverData) {
          removeFromAJAXQueue(property);          // 5
          return serverData;
        }).catch(function(error) {
          removeFromAJAXQueue(property);          // 5
          console.warn(error);
    
          return false;
        });
    
        storeInAJAXQueue(property, ajaxPromise);  // 3
      }
    
      return getAJAXFromQueue(property);          // 4
    }
    
    function getQueueProperty(url, method) {
      return encodeURIComponent(method + url);
    }
    
    function firstTimeRequesting(property) {
      return !ajaxQueue[property];
    }
    
    function removeFromAJAXQueue(property) {
      delete ajaxQueue[property];
    }
    
    function storeInAJAXQueue(property, ajaxPromise) {
      ajaxQueue[property] = ajaxPromise;
    }
    
    function getAJAXFromQueue(property) {
      return ajaxQueue[property];
    }
    

示例:

queueAJAXCalls('http://somedomain.com/api/fetchstuff', 'GET')
.then(function(serverResponse) {
  // do stuff, like using JSON.parse(serverResponse)
})

请注意在一个位置(即someGeneralCodeForFetchingAjaxData)解析jsondata并返回数组和对象的危险,因为这意味着在一个位置更改数组/对象将在所有位置更改它。

我想您也可以使用Service Worker来代替实施此操作。