简体   繁体   English

Javascript-异步/等待数据集保存在循环中

[英]Javascript - Async/Await for Dataset to Save in Loop

I'm creating a fundraising platform of sorts, but am running into some issues which I believe are caused by Async/await within for loops. 我正在创建各种筹款平台,但遇到了一些问题,我认为这些问题是由for循环内的Async / await引起的。

Conceptually, assume I have an array of donation amounts which people have committed. 从概念上讲,假设我有一系列人们承诺的捐赠金额。 When the code executes, it will a take fundraising goal and loop through the donations, charging any un-charged donation commitments until the commitments are exhausted or the fundraising goal is met. 当代码执行时,它将达到筹款目标并遍历捐赠,收取任何未收费的捐赠承诺,直到承诺用尽或达到筹款目标为止。 Then the code updates my database to show which new donation commitments were used, or how much of the commitment is available, so they will not be re-charged in the future. 然后,代码将更新我的数据库,以显示使用了哪些新的捐赠承诺,或有多少可用的承诺,因此将来将不再收取这些费用。 This code individually works fine, but if I try to loop it, it causes errors. 这段代码可以单独运行,但是如果我尝试循环运行,则会导致错误。

I believe the issue is that the future iterations of the loop start executing before the dataset has saved and recognized that some donation commitments were already used. 我认为问题在于,循环的未来迭代会在数据集保存并意识到已经使用了一些捐赠承诺之前开始执行。 I think I need to have the future iterations of the loop await until the prior is saved? 我想我需要等待循环的未来迭代,直到保存之前的迭代?

Is there a proper way to handle this and how would it be done? 是否有适当的方法来处理此问题以及如何完成?

Thanks! 谢谢!

for (let i = 0; i < 2; i++) {
    chargeDonations(proj_sub_id, projItem.price, applications.length, project_fees);
}

function chargeDonations(proj_sub_id, price, quantity, fees) {
    wixData.query("Sponsorships")
    .eq("proj_sub_id", proj_sub_id)
    .ne("allFunds", true)
    .find()
    .then( (results) => {   
        let sponsorships = results.
        let toCharge = (price + fees);

    for (let i = 0; i < sponsorships.length; i++) {
        let amount_charged = sponsorships[i].amountCharged;
        amount_charged = amount_charged || 0;
        let remaining_sponsorship = (sponsorships[i].amount - amount_charged);
        let net_amount = (remaining_sponsorship - calculateFeesStripePhil(remaining_sponsorship, 1));
        let net_toCharge = (toCharge + calculateFeesStripePhil(toCharge));
        let sponsorships_sum = sponsorships.sum("amount");

    if ((toCharge - net_amount) > 0) {
        console.log("Donation Amount" + remaining_sponsorship);
        console.log("Net Amount" + net_amount);
        toCharge -= net_amount;
        console.log("Still to be Charged: " + toCharge);
        sponsorships_sum -= remaining_sponsorship;

    $w("#dataset2").setFilter( wixData.filter()
        .eq("_id", sponsorships[i]._id)) 
        .then( () => {
        $w("#dataset2").setFieldValue('amountCharged', (remaining_sponsorship + amount_charged));
        $w("#dataset2").setFieldValue('allFundsUsed', true);
        console.log("Saved Amount Charged");
        $w("#dataset2").save();
        });

        }
     else {                 
        console.log("Sponsorship Amount " + (toCharge / .921 - 0.3).toFixed(2));
        console.log("Net Amount: " + toCharge);

            $w("#dataset2").setFilter( wixData.filter()
        .eq("_id", sponsorships[i]._id)) 
        .then( () => {
        $w("#dataset2").setFieldValue('amountCharged', (toCharge + amount_charged));                        
        console.log("Saved Amount Charged");
        $w("#dataset2").save();                     
            }); 
        break;
                }
                }

        });

} }

YES - you are correct with your assumption that the next loop iteration is called before the previous one has finished. 是的-您的假设是正确的,即您认为下一个循环迭代是在上一个循环完成之前调用的。 Use of async/await or maybe Promise.all(/* array of promises*/) should solve this issue. 使用async/awaitPromise.all(/* array of promises*/)应该可以解决此问题。

I believe the proper way would be by doing it in this way: 我相信正确的方法是通过这种方式:

for (let i = 0; i < 2; i++) {
    await chargeDonations(...);
}

async function chargeDonations(...) {
    ...
}

Furthermore, I would check with WixCode API for which of the functions in the dataset API (eg save , setFilter ...) and $w API return a Promise and wrap that with async/await block. 此外,我将使用WixCode API检查dataset API中的哪个函数(例如savesetFilter ...)和$w API返回Promise并使用async/await块包装。

Here is something I tried to make you code a bit easier to read and understand: 我尝试使您的代码更易于阅读和理解:

for (let i = 0; i < 2; i++) {
  await chargeDonations(...);
}

async function filterBySubId(filter){
  /*...*/
}
async function filterBySponsorshipId(filter){
  /*...*/
}

async function chargeDonations(proj_sub_id, price, quantity, fees) {
    const results = await filterBySubId();

    let sponsorships = results;
    let toCharge = (price + fees);

    for (let i = 0; i < sponsorships.length; i++) {
      /* I would also put this block in a function and return values */
      let amount_charged = sponsorships[i].amountCharged;
      amount_charged = amount_charged || 0;
      let remaining_sponsorship = (sponsorships[i].amount - amount_charged);
      let net_amount = (remaining_sponsorship - calculateFeesStripePhil(remaining_sponsorship, 1));
      let net_toCharge = (toCharge + calculateFeesStripePhil(toCharge));
      let sponsorships_sum = sponsorships.sum("amount");
      /* end of calculations block */

      if ((toCharge - net_amount) > 0) {
        console.log("Donation Amount" + remaining_sponsorship);
        console.log("Net Amount" + net_amount);
        toCharge -= net_amount;
        console.log("Still to be Charged: " + toCharge);
        sponsorships_sum -= remaining_sponsorship;

        await filterBySponsorshipId(/* your filter */)

        $w("#dataset2").setFieldValue('amountCharged', (remaining_sponsorship + amount_charged));
        $w("#dataset2").setFieldValue('allFundsUsed', true);
        console.log("Saved Amount Charged");
        await $w("#dataset2").save();

      } else {
        console.log("Sponsorship Amount " + (toCharge / .921 - 0.3).toFixed(2));
        console.log("Net Amount: " + toCharge);

        await filterBySponsorshipId(/* your filter */)
        $w("#dataset2").setFieldValue('amountCharged', (toCharge + amount_charged));
        console.log("Saved Amount Charged");
        await $w("#dataset2").save();
        break;
      }
    }
}

Hope it makes sense to you and helps you, Cheers! 希望对您有意义并为您提供帮助,干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM