JavaScript & HTML - 重用来自 fetch() 的数据

JavaScript & HTML - reusing data from fetch()

我正在使用基本提取请求从我的服务器检索 JSON 文件,如下所示:

function getDailyTranscripts (url) {
  fetch(url)
    .then(validateResponse)
    .then(readResponseAsJSON)
    .then(useDailyResult)
    .catch(logError)
}

这会检索一个主 JSON 文件,然后我从中创建变量以使用 charts.js

在单个 html 页面中填充多个图表

目前,我可以通过 运行 将 useDailyResult() 函数中的代码作为我的获取函数的一部分来使它适用于单个图表。但是,我将需要对我的所有图表单独重复此模式,并复制大量代码以及服务器调用,以及我当前的实现。

这里以我的一个图表的当前 useDailyResult 函数为例:

function useDailyResult (result) {

  var labels = Object.keys(getUsersByChannel2(result))
  var data = Object.values(getUsersByChannel2(result))

  var ctx = document.getElementById('chartOops').getContext('2d');
  var chart = new Chart(ctx, {
    type: 'doughnut',
    data: {
      labels: labels,
      datasets: [{
        label: 'Channels',
        data: data
      }]
    },
    options: {
      title: {
        display: true,
        text: 'Users by Channel'
      },
      legend: {
        position: 'bottom'
      },
      scales: {
        gridLines: {
          display: false
        }
      },
      plugins: {
        colorschemes: {
          scheme: chartColorScheme
        }
      }
    }
  });
}

我想要得到的最终结果是从服务器检索一次 JSON 文件,将其存储在本地(例如使用 HTML5 的本地存储),然后 运行 我所有的 chartjs 代码都针对本地存储的文件。这样我就可以减少服务器调用的代码和次数。

我不确定执行此操作的最佳方法,因为我知道访问 JSON 文件的唯一方法是从 fetch 函数中获取。我也一直在研究使用 Backbone.js 因为这可能是一个有用的库。

您可以通过多次调用 p.then 来告诉承诺 p 在可用时调用多个处理程序:

let data = fetch(url)
    .then(validateResponse)
    .then(readResponseAsJSON);

Promise.all([
  data.then(useDailyResult),
  data.then(buildAnotherChart)
]).catch(logError);

如果您只是将数据分配给您的函数可以访问的变量,则可以重复使用从服务器获取的数据。

如果您的链中有另一个 then 分配给一个 var,那么您可以在执行另一次获取之前检查该 var。

var remoteData = {}

function getDailyTranscripts (url) {
  // check for existing response data based on url param
  if(remoteData[url]) {
    console.log('using pre-fetched data from memory')
    useDailyResult(remoteData[url])
  }
  else {
    console.log('fetching from server', url)
    fetch(url)
      .then(validateResponse)
      .then(readResponseAsJSON)
      .then(jsonData => {
        // assuming readResponseAsJSON returns what you want
        remoteData[url] = jsonData
        useDailyResult(jsonData)
      })
      .catch(logError)
  }
}

请注意,如果您在初始提取仍在工作时第二次调用 getDailyTranscripts,它将启动另一次提取。因此,如果这对您来说可能是个问题,您可能需要添加一些逻辑来解决这个问题。

最好 (1) 读取远程数据,然后 (2) 将它传递给任何需要它的东西,如果你提前知道的话。但这仅取决于您的用例。

fetch(url)
  .then(validateResponse)
  .then(readResponseAsJSON)
  .then(handleAllYourChartsAtOnce) // this function could also store the json in a var
  .catch(logError)