Предыстория:
Я использую скрипт таймера для отправки электронных писем, когда выбирается запись. Имена и адреса электронной почты добавляются на страницу запросов. Скрипт проходит по любым именам в списке. Для любых имен, где поле “Уведомлен” пусто, он составляет письмо с некоторым индивидуальным текстом, а затем добавляет запись “Уведомлен” в поле таблицы. В следующий раз, когда скрипт будет запущен, он пропустит отправку письма этому человеку.
Скрипт запускается каждые 10 минут. Это связано с двумя причинами: (a) я хочу, чтобы пользователи имели минуту-две, чтобы отменить действия, если они случайно запросили неправильное имя, и (b) я не хочу дополнительно замедлять систему с помощью триггера на редактирование, когда у нее уже есть другие функции на редактирование, которые потребляют ресурсы.
Проблема:
У меня есть несколько различных таблиц, использующих одинаковую настройку, по одной для каждого пользователя. Каждый день я получаю сообщения об ошибках от многих из этих таблиц, информирующие меня о том, что в скрипте произошла ошибка “Превышено максимальное время”.
Я не знаю, почему это происходит, разве что слишком много скриптов выполняется одновременно. Тем не менее, скрипт довольно короткий, на странице запросов никогда не более 40 записей одновременно, и часто гораздо меньше; на самом деле, много раз ошибка возникает, когда записей для поиска вообще нет, например, посреди ночи или по выходным.
Я хочу оставить уведомления в случае, если скрипт вызовет постоянную ошибку, но, честно говоря, мне все равно, если он иногда будет терпеть неудачу; он все равно отправит следующее письмо. Однако я перегружен сообщениями об ошибках.
Желаемое решение:
Я хочу либо исправить код, чтобы улучшить производительность выполнения скрипта и избежать этих ошибок, либо найти способ добавить строку кода, чтобы тайм-аут скрипта происходил без генерации отчета об ошибках скрипта в таблице.
Код:
Функция отправки письма выглядит следующим образом:
function SendEmail2() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet1 = ss.getSheetByName('Dumbledore requests page');
var data = sheet1.getDataRange().getValues();
var subject = "Приглашение на задержание";
for (var i = 1; i < data.length; i++) {
var email = data[i][9]; // Адрес электронной почты из столбца J
var notifiedStatus = data[i][10]; // Статус из столбца K
if (email && !notifiedStatus) {
var studentName = data[i][0];
var teacherName = data[i][3];
var homeTeacher = data[i][2];
var message = "Здравствуйте " + studentName + ",<br><br>Это письмо информирует вас о том, что у вас задержание с одним из ваших преподавателей (" + teacherName + "), во время вашего следующего свободного периода. Пожалуйста, свяжитесь с вашим куратором свободного периода (" + homeTeacher + ") сразу после обеда, или с вашим замещающим учителем, если таковой имеется, затем идите прямо в кабинет " + teacherName + ", как только вам скажут это сделать.<br><br>Спасибо.<br><br>С уважением,<br>таблица Спарка из Хогвартса";
var replyTo = "[email protected]"; // Адрес электронной почты для ответа
MailApp.sendEmail({
to: email,
subject: subject,
htmlBody: message,
replyTo: replyTo
});
sheet1.getRange(i + 1, 11).setValue("Уведомлен");}}
}
Вопрос:
Как мне оптимизировать код для повышения его эффективности и устранить эти ошибки, или же позволить ему корректно завершить работу, не создавая отчета об ошибке тайм-аута?
Спасибо!
Ответ
Как исправить ошибку "превышено максимальное время" в скрипте отправки электронных писем
Предпосылки:
Ваша текущая ошибка "превышено максимальное время" может возникать из-за нескольких причин, включая количество записей, с которыми обрабатывает скрипт, время выполнения обработки и саму структуру кода. Поскольку скрипт может занимать слишком много времени при выполнении, давайте оптимизируем его.
Решение:
-
Оптимизация цикла: Избегайте вызова
setValue
в каждом проходе цикла. Вместо этого собирайте все значения, которые нужно установить в массив, и устанавливайте их за один раз после завершения обработки всех данных. -
Проверка объема данных: На случай, если данных нет, добавьте проверку перед выполнением всей логики.
- Исключение лишних строк кода: Многие вызовы API требуют времени на выполнение. Мы можем минимизировать их количество.
Отредактированный код может выглядеть следующим образом:
function SendEmail2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Dumbledore requests page');
var data = sheet1.getDataRange().getValues();
var subject = "Detention appointment";
var notifiedStatusUpdates = []; // Массив для хранения обновлений статуса
for (var i = 1; i < data.length; i++) {
var email = data[i][9]; // Электронная почта из столбца J
var notifiedStatus = data[i][10]; // Статус из столбца K
if (email && !notifiedStatus) {
var studentName = data[i][0];
var teacherName = data[i][3];
var homeTeacher = data[i][2];
var message = "Hello " + studentName + ",<br><br>This email is to inform you that you have a detention with one of your professors (" + teacherName + "), during your next free period. Check in with your free period supervisor (" + homeTeacher + ") immediately after your lunch, or your substitute teacher if there is one, then go straight to " + teacherName + "'s room as soon as you're told to do so.<br><br>Thank you.<br><br>Sincerely,<br>the Hogwarts Spreadsheet";
var replyTo = "your_email@example.com"; // Замените своим адресом
MailApp.sendEmail({
to: email,
subject: subject,
htmlBody: message,
replyTo: replyTo
});
notifiedStatusUpdates.push([i + 1, "Notified"]); // Сохраняем данные для обновления
}
}
// Обновление статуса "Notified" в одном вызове
for (var j = 0; j < notifiedStatusUpdates.length; j++) {
sheet1.getRange(notifiedStatusUpdates[j][0], 11).setValue(notifiedStatusUpdates[j][1]);
}
}
Объяснение внесенных изменений:
-
Вместо немедленного обновления значения "Notified", мы собираем все обновления в массив
notifiedStatusUpdates
и затем применяем все изменения за один проход. Это значительно снижает количество обращений к API. -
Проверка, есть ли записи для обработки, таким образом браузер не будет ожидать ненужные данные.
- Убедитесь, что адрес
replyTo
заменен на актуальный.
Другие рекомендации:
-
Периодическая проверка: Убедитесь, что скрипт запускается не слишком часто. Если вы заметили, что количество данных часто уменьшается, вы можете подумать о более длительных интервалах запуска.
- Обработка ошибок: Если вы все еще получаете ошибки, оберните основной код в
try-catch
блок для обработки исключений и чтобы избежать уведомлений, если ошибка не критична.
try {
// основной код
} catch (e) {
Logger.log('Произошла ошибка: ' + e.message);
// возможно, необходимо решить, что делать с ошибкой
}
Эти изменения помогут вам оптимизировать код и, в конечном счете, уменьшить количество ошибок "Maximum time exceeded".