Кэширование данных при использовании Microsoft Graph JavaScript SDK
Кэшируя данные в приложениях JavaScript для совместной работы, подключенных к Microsoft 365, вы можете значительно повысить их производительность и взаимодействие с пользователем. Вот как это сделать.
Приложения для совместной работы в Microsoft 365
Миллионы пользователей ежедневно сотрудничают в Microsoft 365. Подключая свои приложения к данным и аналитическим данным, которые они создают в Microsoft 365, вы можете создавать приложения для совместной работы, которые помогут им работать эффективнее и эффективнее. Microsoft Graph — это API для данных вашей организации, хранящихся в Microsoft 365. А чтобы помочь вам использовать Microsoft Graph в своих приложениях, Microsoft предлагает SDK для самых популярных языков программирования.
Подключайте приложения JavaScript к Microsoft 365
Чтобы подключить приложение JavaScript к Microsoft 365, используйте Microsoft Graph JavaScript SDK. Он предлагает вам простой способ выполнения запросов к Microsoft Graph. Более того, он обрабатывает ответы, включая исключения, за вас, что позволяет вам сосредоточиться на создании своего приложения!
Чтобы начать использовать Microsoft Graph JavaScript SDK, создайте экземпляр клиента Graph с поставщиком проверки подлинности. После этого вы готовы вызывать Microsoft Graph для получения и создания данных в Microsoft 365.
Получение тех же данных из Microsoft 365: эффективно?
Microsoft Graph JavaScript SDK следует вашим инструкциям и извлекает запрошенные вами данные из Microsoft 365. Но по умолчанию он не кэширует полученные данные.
Допустим, вы создаете приложение, в котором хотите показать список людей в вашей команде и файлы, над которыми вы все недавно работали. Если для каждого файла вы хотите показать человека, который изменил файл, вы в конечном итоге загрузите информацию об одном и том же человеке несколько раз. Добавьте к нему аватарку человека, и вы увидите множество повторяющихся запросов. Итак, что вы можете с этим поделать?
Простым решением было бы добавить какое-то кэширование. Но означает ли это, что вам нужно будет изменить все запросы Microsoft Graph, которые вы отправляете в своем приложении? Не совсем! Microsoft Graph JavaScript SDK предлагает лучший способ сделать это. Проверьте это.
ПО промежуточного слоя кэширования для Microsoft Graph JavaScript SDK
Microsoft Graph JavaScript SDK создан с использованием промежуточного программного обеспечения. ПО промежуточного слоя состоит из классов с различными обязанностями, которые применяются к каждому запросу и ответу, выполняемому пакетом SDK Graph. По умолчанию Graph SDK имеет промежуточное ПО для обработки аутентификации, регулирования и выполнения веб-запросов. Но что действительно здорово, так это то, что вы можете создать собственное промежуточное ПО и подключить его к клиенту Microsoft Graph. Это позволяет запускать пользовательский код при каждом запросе, не изменяя сами запросы — идеально подходит для реализации кэширования!
Вот пример ПО промежуточного слоя для кэширования, которое можно использовать с Microsoft Graph JavaScript SDK для кэширования данных в хранилище сеансов браузера:
export function BrowserCacheMiddleware(expirationConfig) {
this.nextMiddleware = undefined;
this.expirationConfig = expirationConfig;
const getHeaders = (headers) => {
const h = {};
for (var header of headers.entries()) {
h[header[0]] = header[1];
}
return h;
};
const blobToDataUrl = async (blob) => {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = function () {
var dataUrl = reader.result;
resolve(dataUrl);
};
reader.readAsDataURL(blob);
});
};
// from https://stackoverflow.com/a/16245768
const dataUrlToBlob = (dataUrl) => {
const blobData = dataUrl.split(',');
const contentType = blobData[0].replace('data:', '').replace(';base64', '');
return b64toBlob(blobData[1], contentType);
};
const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
}
const getExpiresOn = (url) => {
if (!this.expirationConfig) {
return undefined;
}
for (var i = 0; i < this.expirationConfig.length; i++) {
const exp = this.expirationConfig[i];
if (url.indexOf(exp.path) > -1) {
const expiresOn = new Date();
expiresOn.setMinutes(expiresOn.getMinutes() + exp.expirationInMinutes);
return expiresOn;
}
}
return undefined;
}
return {
execute: async (context) => {
console.debug(`Request: ${context.request}`);
const requestKey = btoa(context.request);
let response = window.sessionStorage.getItem(requestKey);
let now = new Date();
if (response) {
const resp = JSON.parse(response);
const expiresOn = resp.expiresOn ? new Date(resp.expiresOn) : undefined;
if (!expiresOn || expiresOn > now) {
console.debug('-- from cache');
let body;
if (resp.headers['content-type'].indexOf('application/json') > -1) {
body = JSON.stringify(resp.body);
}
else {
body = dataUrlToBlob(resp.body);
}
context.response = new Response(body, resp);
return;
}
else {
console.log('-- cache expired');
}
}
console.debug('-- from Graph');
await this.nextMiddleware.execute(context);
if (context.options.method !== 'GET' ||
context.response.status !== 200) {
// don't cache non-GET or failed requests
return;
}
const resp = context.response.clone();
const expiresOn = getExpiresOn(resp.url);
// reset date to catch expiration set to 0
now = new Date();
// don't cache if the item already expired
if (expiresOn <= now) {
return;
}
const headers = getHeaders(resp.headers);
let body = '';
if (headers['content-type'].indexOf('application/json') >= 0) {
body = await resp.json();
}
else {
body = await blobToDataUrl(await resp.blob());
}
response = {
url: resp.url,
status: resp.status,
statusText: resp.statusText,
headers,
body,
expiresOn
};
window.sessionStorage.setItem(requestKey, JSON.stringify(response));
},
setNext: (next) => {
this.nextMiddleware = next;
}
}
};
Точка входа находится в функции execute
, которая получает объект context
с запросом и ответом. Используя URL-адрес запроса, функция создает ключ кеша, который затем используется для проверки того, был ли запрос ранее отправлен и все еще находится в кеше. Если это так, он возвращает ранее кэшированные данные. Если нет, он передает запрос следующему промежуточному программному обеспечению в цепочке. Когда запрос завершен, он проверяет, успешен ли ответ, и кэширует полученные данные. Данные хранятся в кэше сеанса, и функция достаточно умна, чтобы поддерживать как двоичные, так и текстовые данные.
Что еще хорошо в этом промежуточном программном обеспечении, так это то, что вы можете настроить продолжительность кэширования для каждого пути запроса. Например, вы можете кэшировать файлы на 5 минут, но при этом исключить задачи, чтобы всегда получать последний список. Вы можете передать конфигурацию, которая имеет отношение к вашему приложению, при создании экземпляра ПО промежуточного слоя кэша.
Чтобы использовать промежуточное ПО кэширования, его необходимо включить при создании экземпляра клиента Graph из SDK:
Вы должны добавить ПО промежуточного слоя кэша в начало массива ПО промежуточного слоя, используя middleware.unshift()
. Запросы и ответы проходят через классы промежуточного ПО в том порядке, в котором они добавляются в массив промежуточного ПО. Если вы добавите промежуточное ПО кеша в конец массива промежуточного ПО, все запросы будут отправляться к Graph в обход кеша, что противоречит его назначению.
При наличии этого промежуточного ПО Graph SDK будет выполнять запросы только в первый раз. Если данные были получены ранее, а кеш все еще действителен, данные будут обслуживаться из кеша, что значительно повысит производительность вашего приложения.
Прежде чем ты уйдешь
Microsoft Graph JavaScript SDK можно использовать как в браузере, так и на сервере в Node.js. Промежуточное ПО кэширования, которое я показал вам здесь, предназначено для использования в браузере. Если вы хотите использовать его на сервере, вам нужно изменить две вещи.
Во-первых, вам нужно заменить window.sessionStorage
на альтернативу, доступную на сервере в Node.js. Имейте в виду, что он должен правильно обрабатывать несколько интерфейсов (поэтому не храните кеш в памяти сервера). Затем трижды проверьте, не происходит ли утечка данных между сеансами (например, передача данных одного пользователя другому). Это было бы настоящей катастрофой.
к вам
Добавление кеша в ваше приложение JavaScript с помощью Microsoft Graph JavaScript SDK — отличный способ легко повысить производительность вашего приложения. Кэширование данных, получаемых вашим приложением из Microsoft 365, поможет вам уменьшить количество запросов к Microsoft Graph и значительно улучшить взаимодействие с пользователем.
Я показал вам, как вы можете создать промежуточное ПО для кэширования самостоятельно, но если вы хотели бы, чтобы SDK поддерживал его изначально, пожалуйста, проголосуйте за сопутствующую проблему в репозитории SDK. А если у вас есть вопросы или идеи по улучшению, оставляйте комментарии!
📣 Подпишитесь на мою рассылку
Понравилась эта статья? Подпишитесь на мою рассылку новостей и получайте больше советов и рекомендаций из области, доставленных прямо на ваш почтовый ящик.
Первоначально опубликовано на https://blog.mastykarz.nl 28 мая 2021 г.