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

How to make my function wait before it returns another call

我有一项服务可以 return 进行一些翻译。它进行本质上异步的 apex 调用和 returns 翻译。每次我得到一组结果时,我都会将翻译存储在会话存储中,下次来电时,我首先会在缓存的翻译中检查它,如果可用,然后我 return。当用户为同一组值发送多个翻译请求时,问题就来了。为此,我正在跟踪已经在进行中的顶点调用。但是我不确定如何让我的请求等待之前的 apex 调用结束和 return 结果。

这是服务代码。

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

我实际上编写了这个脚本,主要是为了获取从影子页面上的多个元素调用的语言文件 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)
})

注意在一个地方解析 jsondata 的危险,即在 someGeneralCodeForFetchingAjaxData 中,并返回数组和对象,因为这意味着在一个地方更改 array/object 会改变所有地方地点。

除了实现这个,我想你也可以使用 Service Worker.