Как сделать так, чтобы функция выполняла попытку / проверку, не вызывая ошибки? - PullRequest
2 голосов
/ 19 июня 2020

У меня есть много операторов try...catch для случаев, когда входящий пакет JSON может не иметь данных в разделах, где другие JSON могут. Для этого я обычно делаю следующее:

var numberofitems;
try {
    numberofitems = payload.data.form_values["b691"].length;
} catch (err) { numberofitems = 0; }

Однако есть много случаев, когда я могу получить нулевое значение, которое позже испортит мой код. Чтобы очистить свой код, я написал функцию, которая обрабатывает ошибку в одной строке:

function checkTry(toCheck, errVal) {

  try {
    var result = toCheck;
  } catch (err) {
    result = errVal;
  }
  return result;
}

function datacheck() {

  var data;

  var result = checkTry(data.length, "0");
  console.log(result);

}

datacheck();

Тогда мой пример становится следующим:

var numberofitems = checkTry(payload.data.form_values["b691"].length,"0");

Проблема в том, что payload.data.form_values["b691"] выдает ошибку, когда я пытаюсь передать ее в функцию , что привело к ошибке, которую я изначально пытался отловить. Есть ли способ обойти это?

Я сделал JS Bin snippet , чтобы поиграть с проблемой.

Ответы [ 3 ]

2 голосов
/ 19 июня 2020

Решение

Используйте значения по умолчанию и полностью исключите оператор try...catch. Исключение действительно должно быть исключением, с чем вы не умеете обращаться (по крайней мере, try...catch не имеет места в простой деструктуризации объекта):

  1. var numberofitems = (payload.data.form_values.b691 || []).length;
  2. var numberofitems = ((payload.data.form_values || {}).b691 || []).length;
  3. var numberofitems = (((payload.data || {}).form_values || {}).b691 || []).length;
  4. var numberofitems = ((((payload || {}).data || {}).form_values || {}).b691 || []).length;

Подробный обзор

Метод основан на поведение логических операторов. Для логического И, если левая часть равна правдиво , она возвращается, а правая часть не оценивается , если левая часть равна ложь , возвращается правая часть. Обратное верно для логического оператора ИЛИ.

Так как undefined и null являются ложными, а объекты всегда истинны , мы можем с уверенностью предположить, что если объект задан, ИЛИ вернет этот объект и только откатится к оценке нашего значения по умолчанию в случае, если изначально не был предоставлен объект.

Имейте в виду, что метод ограничен всегда истинными / ложными значениями. Например, следующее: indeterministi c с точки зрения того, что имеет value:

const indeterministicTest = () => {
  const rand = Math.floor(Math.random() * 3);
 
  const value = rand === 1 ? 
  null : rand ? true : false;
  
  console.log( value || `The value is ${value}, and I am a fallback string!` );
}

let timeoutId = null;

function runIndefinitely (callback) {
  timeoutId = setTimeout( () => {
    callback();
    runIndefinitely(callback);
  }, 1e3);
}

const start = document.querySelector("#start");
start.addEventListener("click", () =>  {
  runIndefinitely(indeterministicTest);
});

const end = document.querySelector("#end");
end.addEventListener("click", () => {
  timeoutId && clearTimeout(timeoutId);
});
<button id="start" type="button">Start</button>
<button id="end" type="button">End</button>
1 голос
/ 19 июня 2020

вы должны попробовать следующую функцию, которую я писал о времени, когда появился AJAX, и она работает с hastables хорошо сформированными иерархиями пространств имен, как в (продолжить чтение)

Введение бесшовных догадки в JavaScript Определите, существует ли пространство имен / имя-переменной. Перед записью в них проверьте наличие пространства имен в переменных и объектах среды.

Угадайте, существует ли «Book1.chapter22.paragraph37», не вызывая ошибок, и извлеките / отправьте данные, если они существуют, с помощью простейшего выражения:

Синтаксис вызова:

    isNS( [string], [num] )

Пример:

var nsresult =
    isNS( "Book1.chapter22.paragraph37", -1 );
    if( nsresult[0] ){ send( nsresult[1] ) else notify( nsresult[4], nsresult[2] ) };

et c et c

// опустить модификатор или 0, false и undefined для получения логического значения

isNS( "myObject.property.subProperty.myMethod" );
_> Boolean : true/false

Модификатор Возможные значения:

_> -1; (0|false|undefined); ( 1|true ); 2; 3 or 4.

Описание:

(- 1) _> возвращает объект массива, содержащий полную инокуляцию.

(0) _> необязательно; возвращает Boolean: true (если существует полная цепочка NS): false (если она разорвана).

(1) _> если NS * запрос существует, case true: возвращает существующее значение; если нет, case false: возвращает последний допустимый контекст, если он есть, или глобальный объект, если root не существует.

(2) _> возвращает массив существующих пространств имен в запросе аргументов.

(3) _> возвращает массив, содержащий все указанные пространства имен.

(4) _> возвращает исходную строку запроса.

function isNS(arg,f) { /*b.b. Troy III p.a.e.*/
    var i, a = arg.split("."), c = this, s = [], b, r;
    f = f || 0;
        for( i in a ) {
            c ? a[i] in c ? ( c = c[ a[i] ], s.push( a[i] ), b = !0 ) : b = !1 : 0;
        }
    r = [ b, c, s, a, arg ];
    return f < 0 ? r : r[+f||f]
}

* NS - уже означает знакомые инициалы "Пространства имен". [Это всего лишь небольшой кластер на реальном ИИ, но очень важный!]

;
function isNS(arg,f) { /*b.b. Troy III p.a.e.*/
        var i, a = arg.split("."), c = this, s = [], b, r;
        f = f || 0;
            for( i in a ) {
       c ? a[i] in c ? ( c = c[ a[i] ], s.push( a[i] ), b = !0 ) : b = !1 : 0;
            }
        r = [ b, c, s, a, arg ];
        return f < 0 ? r : r[+f||f]
    }
 ;   
 book1 = { 
   chapter1 : { 
       paragraph1 : ["first line","second line"],
       paragraph2 : ["first line","second line"],
       paragraph3 : ["first line","second line"] },
  chapter2 : { 
       paragraph1 : ["first line","second line"],
       paragraph2 : ["first line","second line"],
       paragraph3 : ["first line","second line"] },
  chapter3 : {  
       paragraph1 : ["first line","second line"],
       paragraph2 : ["first line","second line"],
       paragraph3 : ["first line","second line"] }
 }
;

    console.log( 'Boolean for:"book1.chapter2.paragraph3"' )
;
    console.log( isNS("book1.chapter2.paragraph3", 0 ) )
;
    console.log( 'Retrieve:"book1.chapter2.paragraph3"' )
;
    console.log( isNS("book1.chapter2.paragraph3", 1 ) )
;
1 голос
/ 19 июня 2020

Итак, вы не можете этого сделать. Если вы на секунду думаете, как компилятор, вы понимаете проблему: каждый оператор должен быть оценен, прежде чем его можно будет использовать, и любая ошибка должна быть обработана немедленно . В вашем вызове checkTry ваши операторы выполняются следующим образом:

  1. оценивать payload
  2. оценивать payload.data
  3. оценивать payload.form_values["b691"]
  4. оценивать payload.form_values["b691"].length (называть это v1)
  5. Оценивать «0» (называть это v2)
  6. вызывать checkTry (v1, v2)
  7. присваивать результат checkTry numberofitems

Если что-то не присутствует ни на одном из первых 3 шагов, то следующий шаг вызовет ошибку. Проблема в том, что у вашей функции try / catch никогда не было шанса выполнить, и поэтому она никогда не будет работать так, как вы хотите.

Что бы это ни стоило: я не уверен, что имеет смысл пытаться спасти это идея. Тем не менее, вы можете в некотором смысле «отложить» выполнение, заключив это в функцию и передав эту функцию в checktry

Я думаю, это будет выглядеть примерно так:

const risky = () => {payload.data.form_values["b691"].length}
checkTry(risky, "0")
Затем

CheckTry должен выполнить функцию risky внутри try / catch. Однако это должно сработать, это требует больших дополнительных усилий, и что-то, что вам нужно будет повторять снова и снова ... своего рода поражение цели и, возможно, добавление дополнительного уровня сложности для будущих разработчиков.

...