Необязательно передавать переменные / параметры

#javascript

#javascript

Вопрос:

У меня есть несколько вариантов, и, по-видимому, стороннему API не нравится, когда я пытаюсь передать переменные, которые не определены. Это выдаст мне ошибку подписи!

требуется side , symbol , order_type qty и time_in_force

и это то, что я передаю в примере ниже

 mutation {
  setActiveOrder(
    side: "Buy", 
    symbol: "BTCUSD", 
    order_type: "Market", 
    qty: 1, 
    time_in_force: "GoodTillCancel"
  ) {
      data
  }
}
  

но иногда требуется (order_type === "Limit") и price

иногда будет либо одно, либо оба take_profit и stop_loss для любой из двух вышеуказанных возможностей.

при этом я пытаюсь найти наилучший способ необязательной передачи переменных без написания операторов if для каждой возможности сложным способом

Мне бы понравилась другая точка зрения

     settActiveOrder: async (
      _,
      {
        side,
        symbol,
        order_type,
        qty,
        price,
        time_in_force,
        take_profit,
        stop_loss,
        reduce_only,
        close_on_trigger,
        order_link_id,
      },
      ctx
    ) => {
      const setActiveOrder = async () => {
        try {
          return await cclient.placeActiveOrder({
            side: side,
            symbol: symbol,
            order_type: order_type,
            qty: qty,
            // price: price,
            time_in_force: time_in_force,
            // take_profit: take_profit,
            // stop_loss: stop_loss,
            // reduce_only: reduce_only,
            // close_on_trigger: close_on_trigger,
            // order_link_id: order_link_id,
          });
        } catch (error) {
          console.error(error);
        }
      };
      const data = await setActiveOrder();
      return { data: data };
    },
  

Ответ №1:

Если вам нужно создать новый объект (как вы делаете в своем примере), а API сам не обрабатывает значения ‘undefined’, тогда вам нужен способ проверки входных данных и создания объекта условно, но вы можете сделать это в цикле.

Чтобы уточнить, вот ваш код снова, с комментариями:

 settActiveOrder: async (
    _,
    // here you are using "object destructuring".
    // Not existing properties will become a valid,
    // existing variable with the value >>undefined<<
    { side, symbol, order_type, qty, /* ... */ }, 
    ctx
) => { 
    /* ... */

    // here your are building a new object,
    // possibly having existing properties with the value >>undefined<<,
    // but you want these properties to not exist
    return await cclient.placeActiveOrder({
        side: side,
        symbol: symbol,
        order_type: order_type,
        qty: qty,
        /* ... */
    });
    /* ... */
};
  

Решение:

вы могли бы ссылаться на исходный объект вместо использования деструктурирования объекта и перебирать его свойства, например:

 settActiveOrder: async ( _, originalParams, ctx ) => { // <-- no object destructuring
    /* ... */

    // build new object in a loop, but skip undefined properties
    const passedParams = Object.keys( originalParams ).reduce(( acc, key ) => {
        if( typeof originalParams[ key ] === 'undefined' ){
            return acc;
        } else {
            return {
                ...acc,
                [key]: originalParams[ key ]
            }
        }
    }, {});

    return await cclient.placeActiveOrder( passedParams );
    /* ... */
});
  

Альтернативное решение:

В случае, если вам просто нужно передать все определенные свойства, и на самом деле вам не нужно создавать новый объект, тогда вы могли бы просто передать весь объект как есть, вместо использования деструктурирования объекта.

Тогда несуществующие свойства останутся несуществующими свойствами вместо того, чтобы стать существующими свойствами с неопределенным значением.

 settActiveOrder: async ( _, originalParams, ctx ) => {
    /* ... */
    return await cclient.placeActiveOrder( originalParams );
    /* ... */
});
  

Комментарии:

1. Ваше альтернативное решение сработало лучше всего! Это прекрасный пример того, как я усложняю довольно простое решение. Большое вам спасибо за то, что нашли время помочь мне!

Ответ №2:

Я боюсь, что вы не избежите операторов if, но лучшим подходом, чем написание всех комбинаций, было бы объявить словарь и добавить предпочтительные переменные для запроса

Что-то вроде этого:

 var dictForRequest = {

        side: side,
        symbol: symbol,
        order_type: order_type,
        qty: qty,
        time_in_force: time_in_force,
 };
 if(wantPrice)
   dictForRequest["price"] = price;
 if(wantTakeProfit)
   dictForRequest["take_profit"] = take_profit;
 ....
  

Чем передавать dictForRequest в

        ...
      const setActiveOrder = async () => {
    try {
      return await cclient.placeActiveOrder(dictForRequest);        
    } catch (error) {
      console.error(error);
    }
  

Ответ №3:

Вы можете использовать троичные операторы. которые являются операторами if else, но короче и проще в написании.

 {
  price: price ? price : 0,
}

// The above code translates to:

if(price) {
  price = price
  } else {
    price = 0
  }
  

Кроме того, с ES6 вам не обязательно писать это так:

 {
  side: side,
  symbol: symbol,
  order_type: order_type,
}

// These two are the same. You can write it like below.

{
  side,
  symbol,
  order_type
}
  

Приведенный выше код действителен до тех пор, пока имя ключа и имя переменной, передаваемые ключу в качестве значения, совпадают. JS может вычислить и сопоставить правильное значение с правильным ключом, но они должны быть названы точно так же. Кроме того, это правило чувствительно к регистру. Итак, цена: Цена не та. это должно быть price: цена, чтобы это правило оставалось верным.

Если вы ищете другой вариант, кроме троичных операторов, то вы можете инициализировать свои переменные при их объявлении. Но инициализируйте их с помощью ключевого слова let вместо const . Поскольку переменные const неизменяемы -> пусть price = 0;