带有等待和承诺的 useMutation 问题

Posted

技术标签:

【中文标题】带有等待和承诺的 useMutation 问题【英文标题】:Issue with useMutation with await and promise 【发布时间】:2021-02-25 13:59:10 【问题描述】:

我正在最内层循环中执行 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 fetchMoreResult;
      
    )
  

【问题讨论】:

【参考方案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 fetchMoreResult;

//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 )

【讨论】:

以上是关于带有等待和承诺的 useMutation 问题的主要内容,如果未能解决你的问题,请参考以下文章

等待内部带有承诺的 forEach 完成

等待通过 websocket 的承诺

等待但从未解决/拒绝承诺内存使用[重复]

使用 useMutation 可能出现未处理的承诺拒绝警告

Javascript - 异步等待和获取 - 返回值,而不是承诺?

等待承诺链有啥问题?