Проблема с изменением использования с ожиданием и обещанием

#node.js #react-apollo #apollo-client #apollo-server #shopify-app

#node.js #реагировать-apollo #apollo-клиент #apollo-сервер #Shopify-приложение

Вопрос:

Я выполняю операцию useMutation во внутреннем цикле и хочу проверять оставшуюся стоимость при каждой мутации. Но он проверяется после всех мутаций, что является проблемой, потому что по какой-то причине, даже если все мутации выполнены (когда стоимость находится под ограничениями), он вызывает часть .then() для проверки стоимости и ожидания по неизвестной причине.

Редактировать: я также заметил, что, несмотря на то, что программа ожидает снова и снова, состояние сети Chrome показывает, что все мутации произошли, и только запрос handleDiscountMore, т.е. fetchMore, находится в ожидании

 const { loading, error, data, fetchMore, extensions, refetch } = useQuery(GET_COLLECTION, {
    variables: { "id": coll.collection.id }
  });

const [updatePrice] = useMutation(UPDATE_PRICE);

const redirectToModify = async (data, totalProducts) => {
    wait(20000);
    var cursor, fetchCount;
    fetchCount = data.collection.products.edges.length;
    totalProducts -= fetchCount;

    data.collection.products.edges.map(async(product) => {
      const results = await Promise.all(product.node.variants.edges.map(variant => {
        if (selected == 'curr_price') {
          //do stuff
        }
        else {
          //do stuff
        }
        const productVariableInput = {
          //Object
        };

        updatePrice({ variables: { input: productVariableInput } }).then(({ data, extensions }) => {
          console.log("Remaining", extensions.cost.throttleStatus.currentlyAvailable) 
          console.log(data)
          if (extensions.cost.throttleStatus.currentlyAvailable < 100) {
            console.log("WAITING")
            wait(18000);
          }
        }).catch(e => {
          console.log(e)
        })
        console.log("AFTER")
        return 0;
      }))
    })
        
    if (totalProducts > 0) {
      console.log("Calling")
      wait(15000);
      handleDiscountMore(data, cursor, totalProducts)  
    }
  };

//Below function is Just for reference. It gets called before checking the throttleStatus above. afaik there's no problem with this

const handleDiscountMore = (data, cursor, pc) => { 
    console.log("Call received")
    fetchMore({
      variables: {
        "id": data.collection.id,
        "cursor": cursor
      },
      updateQuery: (
        previousResult,
        { fetchMoreResult }
      ) => {
        console.log("adding", fetchMoreResult);
        redirectToModify(fetchMoreResult, pc);
        // return fetchMoreResu<
      }
    })
  }
  

Ответ №1:

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

 const id = coll.collection.id;
const { loading, error, data, fetchMore, extensions, refetch } = useQuery(GET_COLLECTION, {
    variables: { id }
});

const [updatePrice] = useMutation(UPDATE_PRICE);

// Given a product, returns a promise that resolves when all variants are processed
async function process_product(product){
    const variants = product.node.variants.edges;
    for (let i = 0; i < variants.length; i  ){
        await process_variant(variants[i]);
    }
}

// Given a variant, returns a promise after the product is processed
async function process_variant(variant){
    if (variant) {
        console.log('doing stuff')
    }
    else {
        console.log('doing other stuff')
    }
    const productVariableInput = {};
    const variables = { input: productVariableInput };

    try {
        const {data, extensions} = await updatePrice({ variables });
        const remaining_throttle = extensions.cost.throttleStatus.currentlyAvailable;
        console.log("Remaining", remaining_throttle)
        console.log(data)

        // Change to a while loop to make sure you actually wait until resources are available
        if (remaining_throttle < 100) {
            console.log("WAITING")
            await wait(18000);
        }
    } catch (e) {
        console.log('error:', e);
    }
    console.log("AFTER")
    return 0;
}

const redirectToModify = async (data, totalProducts) => {
    await wait(20000);
    let cursor;
    const products = data.collection.product.edges;

    totalProducts = totalProducts - products.length;

    // Wait for all products to finish processing
    for (var i = 0; i < products.length; i  ){
        await process_product(products[i]);
    }

    if (totalProducts > 0) {
        console.log("Calling")
        await wait(15000);
        handleDiscountMore(data, cursor, totalProducts)
    }
};

function updateQuery(previousResult, { fetchMoreResult }){
    console.log("adding", fetchMoreResult);
    redirectToModify(fetchMoreResult, pc);
    return fetchMoreResu<
}
//Below function is Just for reference. It gets called before checking the throttleStatus above. afaik there's no problem with this
function handleDiscountMore(data, cursor, pc) {
    console.log("Call received")
    const variables = { id: data.collection.id, cursor };
    fetchMore({ variables, updateQuery })
}