{"id":897,"date":"2024-09-24T20:27:01","date_gmt":"2024-09-24T20:27:01","guid":{"rendered":"https:\/\/algocademy.com\/blog\/wix-understanding-async-and-await-for-better-web-development\/"},"modified":"2025-03-07T18:42:08","modified_gmt":"2025-03-07T18:42:08","slug":"wix-understanding-async-and-await-for-better-web-development","status":"publish","type":"post","link":"https:\/\/algocademy.com\/blog\/wix-understanding-async-and-await-for-better-web-development\/","title":{"rendered":"Wix: Understanding Async and Await for Better Web Development"},"content":{"rendered":"<article>\n<p>In the world of web development, understanding how to manage asynchronous tasks is essential. This article explores the concepts of async and await in Wix, providing insights that can help improve your coding skills. By breaking down complex topics into simpler ideas, we aim to make learning about these powerful tools accessible to everyone, even beginners. Let&#8217;s dive in!<\/p>\n<h3>Key Takeaways<\/h3>\n<ul>\n<li>Async and await help make asynchronous code easier to read and write.<\/li>\n<li>Using async functions allows you to handle tasks without blocking the main program.<\/li>\n<li>Avoiding callback hell is crucial for keeping your code clean and manageable.<\/li>\n<li>Proper error handling is essential when working with async functions.<\/li>\n<li>Optimizing your use of async and await can enhance your website&#8217;s performance.<\/li>\n<\/ul>\n<h2>Introduction to Async and Await in Wix<\/h2>\n<p><img decoding=\"async\" style=\"max-width: 100%; max-height: 200px;\" src=\"https:\/\/contenu.nyc3.digitaloceanspaces.com\/journalist\/079c4604-df12-4d5e-ac7c-737eef373861\/thumbnail.jpeg\" alt=\"Computer screen with code snippets in a workspace.\"><\/p>\n<h3>Understanding Asynchronous JavaScript<\/h3>\n<p>Asynchronous JavaScript allows your code to run without waiting for tasks to finish. This means you can do other things while waiting for a response, like fetching data from a server. <strong>Async and await<\/strong> are tools that help make this easier and cleaner. In 2024, these features have become standard practice for modern web development in platforms like Wix.<\/p>\n<h3>The Evolution of Async and Await<\/h3>\n<p>Before async and await, developers used callbacks and promises to handle asynchronous tasks. With the introduction of async and await in ES2017, writing asynchronous code became simpler. Instead of chaining multiple <code>.then()<\/code> calls, you can write code that looks more like regular, synchronous code. This evolution has significantly improved code readability and maintainability, especially in complex Wix applications.<\/p>\n<h3>Why Use Async and Await in Wix<\/h3>\n<p>Using async and await in Wix can improve your web development experience. Here are some compelling reasons:<\/p>\n<ul>\n<li><strong>Cleaner Code<\/strong>: It reduces the complexity of your code, making it more maintainable.<\/li>\n<li><strong>Easier Debugging<\/strong>: Errors are easier to track down with more straightforward execution flow.<\/li>\n<li><strong>Better Performance<\/strong>: It allows your application to run more smoothly by preventing UI blocking.<\/li>\n<li><strong>Improved User Experience<\/strong>: Your website remains responsive even during data-intensive operations.<\/li>\n<\/ul>\n<blockquote>\n<p>\nAsync and await make it easier to handle tasks that take time, like fetching data or waiting for user input. This leads to a better user experience and more efficient code.\n<\/p>\n<\/blockquote>\n<p>In Wix, you can leverage async\/await with <a href=\"https:\/\/www.wix.com\/studio\/academy\/tutorials\/backend-web-methods-wix-studio\" rel=\"noopener noreferrer\" target=\"_blank\">backend functions and web methods<\/a>. This integration allows for more dynamic and responsive web applications, enabling seamless communication between frontend and backend components.<\/p>\n<h2>Setting Up Your Wix Environment for Async\/Await<\/h2>\n<h3>Installing Necessary Tools<\/h3>\n<p>To start using async and await in Wix, you need to set up your environment properly. Here are the updated steps for 2024:<\/p>\n<ol>\n<li><strong>Install the Wix CLI<\/strong>: This tool helps you manage your Wix projects efficiently. Use npm to install it globally with <code>npm install -g @wix\/cli<\/code>.<\/li>\n<li><strong>Create a New Project<\/strong>: Use the command <code>wix create-app my-app<\/code> to create a new Wix project with the latest templates.<\/li>\n<li><strong>Add API Extensions<\/strong>: You can <a href=\"https:\/\/dev.wix.com\/docs\/build-apps\/develop-your-app\/frameworks\/wix-cli\/supported-extensions\/backend-extensions\/api\/add-api-extensions-with-the-cli\" rel=\"noopener noreferrer\" target=\"_blank\">add API extensions with the CLI<\/a>. For example, navigate to your project repo and run <code>wix generate extension api<\/code>. The CLI will display a menu of extensions to generate.<\/li>\n<\/ol>\n<h3>Configuring Your Wix Project<\/h3>\n<p>Once you have the necessary tools, configure your project for optimal async\/await usage:<\/p>\n<ul>\n<li>Open your project in the Wix Editor or Wix Studio.<\/li>\n<li>For Wix Editor: Go to the <strong>Settings<\/strong> tab and enable <strong>Velo by Wix<\/strong>.<\/li>\n<li>For Wix Studio: Velo is enabled by default, allowing you to immediately start coding.<\/li>\n<li>Set up your database collections, as they will be essential for async operations.<\/li>\n<li>Configure your package.json to include any additional dependencies you might need.<\/li>\n<\/ul>\n<h3>Testing Your Setup<\/h3>\n<p>After configuration, it&#8217;s important to test your setup with a simple async function:<\/p>\n<ul>\n<li>Create a test async function to fetch data from your database.<\/li>\n<li>Use console logs to verify that the data is being fetched correctly.<\/li>\n<li>Check that your UI updates as expected when the data is retrieved.<\/li>\n<li>Test error scenarios to ensure proper error handling is in place.<\/li>\n<\/ul>\n<blockquote>\n<p>\nSetting up your environment correctly is crucial for effective web development. It ensures that you can utilize async and await features without issues and sets the foundation for a robust application.\n<\/p>\n<\/blockquote>\n<h2>Basic Concepts of Async and Await<\/h2>\n<h3>Promises vs Callbacks<\/h3>\n<p>Asynchronous programming in JavaScript can be handled using <strong>callbacks<\/strong> or <strong>promises<\/strong>. Here&#8217;s an updated comparison for 2024:<\/p>\n<table>\n<thead>\n<tr>\n<th>Feature<\/th>\n<th>Callbacks<\/th>\n<th>Promises<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Readability<\/td>\n<td>Can become messy with nesting (callback hell)<\/td>\n<td>More readable and manageable<\/td>\n<\/tr>\n<tr>\n<td>Error Handling<\/td>\n<td>Difficult to manage consistently<\/td>\n<td>Easier with <code>.catch()<\/code> and centralized handling<\/td>\n<\/tr>\n<tr>\n<td>Execution Flow<\/td>\n<td>Sequential, can lead to blocking<\/td>\n<td>Non-blocking, allows parallel tasks<\/td>\n<\/tr>\n<tr>\n<td>Composition<\/td>\n<td>Challenging to compose multiple operations<\/td>\n<td>Easy to chain and compose with <code>Promise.all()<\/code><\/td>\n<\/tr>\n<tr>\n<td>Modern Support<\/td>\n<td>Legacy approach, still used in some libraries<\/td>\n<td>Modern standard, widely supported<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Async Functions Explained<\/h3>\n<p>An <strong>async function<\/strong> is a special type of function that allows you to use the <code>await<\/code> keyword inside it. This makes it easier to work with asynchronous code. When you declare a function as <code>async<\/code>, it automatically returns a promise, even if you don&#8217;t explicitly return one.<\/p>\n<p>Here&#8217;s a simple example of an async function in Wix:<\/p>\n<pre><code class=\"language-javascript\">async function getUserData(userId) {\n    \/\/ This function automatically returns a promise\n    const userRecord = await wixData.get(\"Users\", userId);\n    return userRecord;\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Statements\/async_function\" rel=\"noopener noreferrer\" target=\"_blank\">Async functions<\/a> enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.<\/p>\n<h3>The Role of Await in JavaScript<\/h3>\n<p>The <code>await<\/code> keyword is used to pause the execution of an async function until a promise is resolved or rejected. This means you can write code that looks synchronous, making it easier to read and understand. Here&#8217;s a practical example:<\/p>\n<pre><code class=\"language-javascript\">async function fetchUserAndOrders() {\n    \/\/ Execution pauses here until the promise resolves\n    const user = await wixData.get(\"Users\", currentUserId);\n    \n    \/\/ Once user data is available, fetch their orders\n    const orders = await wixData.query(\"Orders\")\n        .eq(\"userId\", user._id)\n        .find();\n    \n    return {\n        userData: user,\n        userOrders: orders.items\n    };\n}\n<\/code><\/pre>\n<blockquote>\n<p>\nUsing async and await can greatly improve the clarity of your code, making it easier to follow the flow of operations. It transforms promise-based code into something that resembles synchronous code, without blocking the main thread.\n<\/p>\n<\/blockquote>\n<p>In summary, understanding these basic concepts is crucial for effectively using async and await in your Wix projects. They help in managing asynchronous operations without getting lost in complex callback structures or promise chains.<\/p>\n<h2>Implementing Async and Await in Wix Velo<\/h2>\n<h3>Writing Your First Async Function<\/h3>\n<p>To get started with async functions in Wix Velo, you need to define a function using the <code>async<\/code> keyword. This allows you to use <code>await<\/code> inside the function. Here&#8217;s an updated example for 2024:<\/p>\n<pre><code class=\"language-javascript\">import wixData from 'wix-data';\n\nexport async function fetchProducts() {\n    try {\n        \/\/ Await the query result\n        const results = await wixData.query(\"Products\")\n            .limit(10)\n            .sort(\"createdDate\", \"desc\")\n            .find();\n        \n        \/\/ Return the items array from the results\n        return results.items;\n    } catch (error) {\n        console.error(\"Error fetching products:\", error);\n        throw error; \/\/ Rethrow to allow proper handling by caller\n    }\n}\n<\/code><\/pre>\n<h3>Using Await with Wix Data API<\/h3>\n<p>When working with the Wix Data API, using <code>await<\/code> helps you manage data fetching without blocking the rest of your code. Here&#8217;s a comprehensive approach:<\/p>\n<ol>\n<li><strong>Define your async function<\/strong> with proper error handling.<\/li>\n<li><strong>Use <code>await<\/code> for database operations<\/strong> like querying, inserting, or updating.<\/li>\n<li><strong>Process the results<\/strong> once the data is ready.<\/li>\n<li><strong>Update UI elements<\/strong> with the processed data.<\/li>\n<\/ol>\n<p>Here&#8217;s an example of loading data into a repeater:<\/p>\n<pre><code class=\"language-javascript\">import wixData from 'wix-data';\n\n$w.onReady(function() {\n    loadProducts();\n});\n\nasync function loadProducts() {\n    try {\n        \/\/ Show loading indicator\n        $w(\"#loadingIndicator\").show();\n        \n        \/\/ Fetch data with await\n        const results = await wixData.query(\"Products\")\n            .eq(\"inStock\", true)\n            .limit(20)\n            .find();\n        \n        \/\/ Process data if needed\n        const processedItems = results.items.map(item => {\n            return {\n                ...item,\n                formattedPrice: \"$\" + item.price.toFixed(2),\n                isOnSale: item.discount > 0\n            };\n        });\n        \n        \/\/ Update UI\n        $w(\"#productsRepeater\").data = processedItems;\n        \n        \/\/ Hide loading indicator\n        $w(\"#loadingIndicator\").hide();\n    } catch (error) {\n        \/\/ Handle errors\n        console.error(\"Failed to load products:\", error);\n        $w(\"#errorMessage\").text = \"Failed to load products. Please try again.\";\n        $w(\"#errorMessage\").show();\n        $w(\"#loadingIndicator\").hide();\n    }\n}\n<\/code><\/pre>\n<h3>Common Pitfalls and How to Avoid Them<\/h3>\n<p>When using async and await in Wix, be aware of these common mistakes and their solutions:<\/p>\n<ul>\n<li><strong>Forgetting to use <code>await<\/code><\/strong>: If you don&#8217;t await a promise, you&#8217;ll get a Promise object instead of its resolved value. Always use await with promise-returning functions.<\/li>\n<li><strong>Missing error handling<\/strong>: Wrap async code in try-catch blocks to prevent unhandled promise rejections.<\/li>\n<li><strong>Awaiting inside loops<\/strong>: This runs operations sequentially. Use <code>Promise.all()<\/code> for parallel execution.<\/li>\n<li><strong>Not handling loading states<\/strong>: Always show loading indicators during async operations to improve user experience.<\/li>\n<li><strong>Mixing sync and async code improperly<\/strong>: Be consistent in your approach to avoid confusion.<\/li>\n<\/ul>\n<p>Here&#8217;s an example of properly handling multiple async operations in parallel:<\/p>\n<pre><code class=\"language-javascript\">async function loadDashboardData() {\n    try {\n        \/\/ Start all requests simultaneously\n        const [userPromise, ordersPromise, productsPromise] = [\n            wixData.get(\"Users\", currentUserId),\n            wixData.query(\"Orders\").eq(\"userId\", currentUserId).find(),\n            wixData.query(\"Products\").limit(5).find()\n        ];\n        \n        \/\/ Wait for all to complete\n        const [user, orders, products] = await Promise.all([\n            userPromise, ordersPromise, productsPromise\n        ]);\n        \n        \/\/ Now update UI with all data available\n        updateDashboard(user, orders, products);\n    } catch (error) {\n        handleError(error);\n    }\n}\n<\/code><\/pre>\n<blockquote>\n<p>\nRemember: Async functions always return promises, so handle them properly throughout your application to maintain a consistent flow and avoid unexpected behavior.\n<\/p>\n<\/blockquote>\n<p>By following these guidelines, you can effectively implement async and await in your Wix Velo projects, making your web development smoother and more efficient. <strong>This approach allows you to <a href=\"https:\/\/dev.wix.com\/docs\/develop-websites\/articles\/coding-with-velo\/backend-code\/web-modules\/call-backend-code-from-the-frontend\" rel=\"noopener noreferrer\" target=\"_blank\">call backend code from the frontend<\/a><\/strong> seamlessly, enhancing your application&#8217;s performance and user experience.<\/p>\n<h2>Advanced Async\/Await Techniques in Wix<\/h2>\n<h3>Error Handling in Async Functions<\/h3>\n<p>Proper error handling is crucial when working with async functions in Wix. Here are some advanced techniques for 2024:<\/p>\n<ul>\n<li><strong>Structured try-catch blocks<\/strong>: Organize your code to catch specific errors at different levels.<\/li>\n<li><strong>Custom error classes<\/strong>: Create specialized error types for better error identification.<\/li>\n<li><strong>Centralized error handling<\/strong>: Implement a consistent approach across your application.<\/li>\n<\/ul>\n<p><strong>Example of advanced error handling:<\/strong><\/p>\n<pre><code class=\"language-javascript\">\/\/ Custom error class\nclass DataFetchError extends Error {\n    constructor(message, entityType, operation) {\n        super(message);\n        this.name = \"DataFetchError\";\n        this.entityType = entityType;\n        this.operation = operation;\n        this.timestamp = new Date();\n    }\n}\n\nasync function fetchUserProfile(userId) {\n    try {\n        \/\/ Main data fetch\n        const user = await wixData.get(\"Users\", userId);\n        \n        \/\/ Check if user exists\n        if (!user) {\n            throw new DataFetchError(\n                \"User not found\", \n                \"User\", \n                \"get\"\n            );\n        }\n        \n        try {\n            \/\/ Nested operation that might fail independently\n            const preferences = await wixData.query(\"UserPreferences\")\n                .eq(\"userId\", userId)\n                .find();\n                \n            return {\n                ...user,\n                preferences: preferences.items[0] || null\n            };\n        } catch (preferencesError) {\n            \/\/ Log but don't fail the whole operation\n            console.error(\"Failed to fetch preferences:\", preferencesError);\n            \n            \/\/ Return user data without preferences\n            return {\n                ...user,\n                preferences: null,\n                preferencesError: true\n            };\n        }\n    } catch (error) {\n        \/\/ Log detailed error information\n        console.error(`Error in fetchUserProfile: ${error.message}`, {\n            error,\n            userId,\n            timestamp: new Date()\n        });\n        \n        \/\/ Rethrow with additional context if needed\n        if (error instanceof DataFetchError) {\n            throw error;\n        } else {\n            throw new DataFetchError(\n                \"Failed to fetch user profile\", \n                \"User\", \n                \"get\"\n            );\n        }\n    }\n}\n<\/code><\/pre>\n<h3>Chaining Promises with Async\/Await<\/h3>\n<p>Chaining promises becomes much cleaner with async\/await. Here are some advanced patterns:<\/p>\n<ol>\n<li><strong>Sequential processing<\/strong>: Execute operations in a specific order when each depends on the previous result.<\/li>\n<li><strong>Parallel processing with dependencies<\/strong>: Start independent operations in parallel, then process their results together.<\/li>\n<li><strong>Dynamic chaining<\/strong>: Create chains based on conditional logic.<\/li>\n<\/ol>\n<p><strong>Example of advanced promise chaining:<\/strong><\/p>\n<pre><code class=\"language-javascript\">async function processOrderWorkflow(orderId) {\n    \/\/ Get the order details\n    const order = await wixData.get(\"Orders\", orderId);\n    \n    \/\/ Process payment and inventory in parallel\n    const [paymentResult, inventoryResult] = await Promise.all([\n        processPayment(order),\n        updateInventory(order.items)\n    ]);\n    \n    \/\/ Sequential steps that depend on both payment and inventory\n    if (paymentResult.success && inventoryResult.success) {\n        \/\/ Update order status\n        const updatedOrder = await wixData.update(\"Orders\", {\n            ...order,\n            status: \"confirmed\",\n            paymentId: paymentResult.transactionId\n        });\n        \n        \/\/ Send confirmation email\n        await sendOrderConfirmation(updatedOrder);\n        \n        \/\/ Return final result\n        return {\n            success: true,\n            order: updatedOrder,\n            message: \"Order processed successfully\"\n        };\n    } else {\n        \/\/ Handle failures\n        await handleOrderProcessingFailure(\n            order, \n            paymentResult, \n            inventoryResult\n        );\n        \n        return {\n            success: false,\n            message: \"Order processing failed\",\n            paymentSuccess: paymentResult.success,\n            inventorySuccess: inventoryResult.success\n        };\n    }\n}\n<\/code><\/pre>\n<h3>Optimizing Performance with Async\/Await<\/h3>\n<p>To ensure your Wix site runs efficiently, consider these advanced optimization techniques:<\/p>\n<ul>\n<li><strong>Strategic parallelization<\/strong>: Use <code>Promise.all()<\/code> for operations that can run simultaneously.<\/li>\n<li><strong>Implement caching<\/strong>: Store frequently accessed data to reduce database calls.<\/li>\n<li><strong>Lazy loading<\/strong>: Load data only when needed, especially for content below the fold.<\/li>\n<li><strong>Request batching<\/strong>: Combine multiple small requests into a single larger request.<\/li>\n<li><strong>Prioritization<\/strong>: Load critical data first, then less important data.<\/li>\n<\/ul>\n<p><strong>Example of performance optimization:<\/strong><\/p>\n<pre><code class=\"language-javascript\">\/\/ Cache implementation\nconst cache = new Map();\nconst CACHE_TTL = 5 * 60 * 1000; \/\/ 5 minutes in milliseconds\n\nasync function getCachedData(collectionName, query, forceRefresh = false) {\n    const cacheKey = `${collectionName}:${JSON.stringify(query)}`;\n    \n    \/\/ Check if data is in cache and not expired\n    const cachedItem = cache.get(cacheKey);\n    const now = Date.now();\n    \n    if (!forceRefresh && cachedItem && (now - cachedItem.timestamp < CACHE_TTL)) {\n        console.log(`Cache hit for ${cacheKey}`);\n        return cachedItem.data;\n    }\n    \n    \/\/ Cache miss or forced refresh, fetch from database\n    console.log(`Cache miss for ${cacheKey}, fetching fresh data`);\n    const freshData = await wixData.query(collectionName)\n        .hasSome(query.field, query.values)\n        .find();\n    \n    \/\/ Update cache\n    cache.set(cacheKey, {\n        data: freshData,\n        timestamp: now\n    });\n    \n    return freshData;\n}\n\n\/\/ Usage in page code\nasync function loadProductPage() {\n    \/\/ Start loading critical data immediately\n    const productPromise = wixData.get(\"Products\", productId);\n    \n    \/\/ Update UI with critical data as soon as it's available\n    const product = await productPromise;\n    $w(\"#productTitle\").text = product.title;\n    $w(\"#productPrice\").text = `$${product.price.toFixed(2)}`;\n    $w(\"#productImage\").src = product.mainImage;\n    \n    \/\/ Now load non-critical data in parallel\n    $w(\"#relatedProductsSection\").collapse();\n    $w(\"#reviewsSection\").collapse();\n    \n    const [relatedProducts, reviews] = await Promise.all([\n        \/\/ Use cached data for related products\n        getCachedData(\"Products\", {\n            field: \"category\",\n            values: [product.category]\n        }),\n        \/\/ Always get fresh reviews\n        wixData.query(\"Reviews\")\n            .eq(\"productId\", productId)\n            .limit(5)\n            .find()\n    ]);\n    \n    \/\/ Update UI with non-critical data\n    displayRelatedProducts(relatedProducts.items);\n    displayReviews(reviews.items);\n    \n    $w(\"#relatedProductsSection\").expand();\n    $w(\"#reviewsSection\").expand();\n}\n<\/code><\/pre>\n<blockquote>\n<p>\nTip: Always test your async functions to ensure they perform well under load. Use the Wix Editor's built-in profiling tools to identify performance bottlenecks in your code.\n<\/p>\n<\/blockquote>\n<p>By mastering these advanced techniques, you can enhance your web development skills and create more efficient applications in Wix Velo. Remember, <strong>effective error handling<\/strong> and performance optimization are key to successful async programming!<\/p>\n<h2>Practical Examples of Async and Await in Wix<\/h2>\n<h3>Fetching Data Asynchronously<\/h3>\n<p>When working with data in Wix, you often need to fetch it from a database. Using <strong>async and await<\/strong> makes this process smoother. Here's a modern example for 2024:<\/p>\n<pre><code class=\"language-javascript\">import wixData from 'wix-data';\n\n\/\/ Function to fetch products with filters\nexport async function fetchFilteredProducts(category, minPrice, maxPrice, sortBy) {\n    console.log(\"Starting to fetch filtered products...\");\n    \n    try {\n        \/\/ Build query dynamically\n        let query = wixData.query(\"Products\");\n        \n        \/\/ Apply filters conditionally\n        if (category) {\n            query = query.eq(\"category\", category);\n        }\n        \n        if (minPrice !== undefined) {\n            query = query.ge(\"price\", minPrice);\n        }\n        \n        if (maxPrice !== undefined) {\n            query = query.le(\"price\", maxPrice);\n        }\n        \n        \/\/ Apply sorting\n        if (sortBy === \"priceLowToHigh\") {\n            query = query.ascending(\"price\");\n        } else if (sortBy === \"priceHighToLow\") {\n            query = query.descending(\"price\");\n        } else if (sortBy === \"newest\") {\n            query = query.descending(\"_createdDate\");\n        }\n        \n        \/\/ Execute query\n        const results = await query.find();\n        console.log(`Fetched ${results.items.length} products successfully`);\n        \n        return {\n            items: results.items,\n            totalCount: results.totalCount,\n            hasNext: results.hasNext()\n        };\n    } catch (error) {\n        console.error(\"Error fetching filtered products:\", error);\n        throw error;\n    }\n}\n<\/code><\/pre>\n<p>In this code:<\/p>\n<ol>\n<li>The function accepts multiple parameters for filtering and sorting.<\/li>\n<li>It dynamically builds a query based on the provided filters.<\/li>\n<li>It awaits the query execution without blocking the UI.<\/li>\n<li>It returns a structured response with the results and metadata.<\/li>\n<\/ol>\n<h3>Updating UI Elements with Async Data<\/h3>\n<p>You can use async functions to create dynamic and responsive UI elements. Here's an example of a product page that loads data progressively:<\/p>\n<pre><code class=\"language-javascript\">import wixData from 'wix-data';\nimport wixUsers from 'wix-users';\n\n$w.onReady(function() {\n    loadProductDetails();\n    \n    $w(\"#addToCartButton\").onClick(() => addToCart());\n});\n\nasync function loadProductDetails() {\n    try {\n        \/\/ Show loading states\n        $w(\"#productContainer\").hide();\n        $w(\"#loadingIndicator\").show();\n        \n        \/\/ Get product ID from URL\n        const productId = getProductIdFromUrl();\n        \n        \/\/ Load main product data\n        const product = await wixData.get(\"Products\", productId);\n        \n        \/\/ Update main product information\n        $w(\"#productTitle\").text = product.title;\n        $w(\"#productDescription\").html = product.description;\n        $w(\"#productPrice\").text = `$${product.price.toFixed(2)}`;\n        $w(\"#productImage\").src = product.mainImage;\n        \n        \/\/ Show the product container\n        $w(\"#productContainer\").show();\n        $w(\"#loadingIndicator\").hide();\n        \n        \/\/ Load additional data in the background\n        loadAdditionalProductData(product);\n    } catch (error) {\n        console.error(\"Error loading product:\", error);\n        $w(\"#errorMessage\").text = \"Failed to load product details.\";\n        $w(\"#errorMessage\").show();\n        $w(\"#loadingIndicator\").hide();\n    }\n}\n\nasync function loadAdditionalProductData(product) {\n    try {\n        \/\/ Show loading states for secondary sections\n        $w(\"#reviewsContainer\").hide();\n        $w(\"#relatedProductsContainer\").hide();\n        $w(\"#secondaryLoading\").show();\n        \n        \/\/ Load reviews and related products in parallel\n        const [reviews, relatedProducts] = await Promise.all([\n            wixData.query(\"Reviews\")\n                .eq(\"productId\", product._id)\n                .limit(5)\n                .find(),\n            wixData.query(\"Products\")\n                .eq(\"category\", product.category)\n                .ne(\"_id\", product._id)\n                .limit(4)\n                .find()\n        ]);\n        \n        \/\/ Update reviews section\n        if (reviews.items.length > 0) {\n            $w(\"#reviewsRepeater\").data = reviews.items;\n            $w(\"#reviewsContainer\").show();\n            $w(\"#noReviewsMessage\").hide();\n        } else {\n            $w(\"#noReviewsMessage\").show();\n        }\n        \n        \/\/ Update related products\n        if (relatedProducts.items.length > 0) {\n            $w(\"#relatedProductsRepeater\").data = relatedProducts.items;\n            $w(\"#relatedProductsContainer\").show();\n        }\n        \n        \/\/ Hide loading indicator\n        $w(\"#secondaryLoading\").hide();\n    } catch (error) {\n        console.error(\"Error loading additional data:\", error);\n        $w(\"#secondaryLoading\").hide();\n    }\n}\n\nasync function addToCart() {\n    try {\n        \/\/ Show loading state on button\n        $w(\"#addToCartButton\").disable();\n        $w(\"#addToCartButton\").label = \"Adding...\";\n        \n        \/\/ Get current user\n        const currentUser = wixUsers.currentUser;\n        const isLoggedIn = await currentUser.loggedIn();\n        \n        if (!isLoggedIn) {\n            \/\/ Handle guest checkout or prompt login\n            $w(\"#loginPrompt\").show();\n            return;\n        }\n        \n        \/\/ Get product ID and quantity\n        const productId = getProductIdFromUrl();\n        const quantity = $w(\"#quantityInput\").value;\n        \n        \/\/ Add to cart via backend function\n        await addProductToCart(productId, quantity);\n        \n        \/\/ Show success message\n        $w(\"#successMessage\").show();\n        setTimeout(() => $w(\"#successMessage\").hide(), 3000);\n    } catch (error) {\n        console.error(\"Error adding to cart:\", error);\n        $w(\"#errorMessage\").text = \"Failed to add product to cart.\";\n        $w(\"#errorMessage\").show();\n    } finally {\n        \/\/ Reset button state\n        $w(\"#addToCartButton\").enable();\n        $w(\"#addToCartButton\").label = \"Add to Cart\";\n    }\n}\n<\/code><\/pre>\n<h3>Handling Multiple Async Operations<\/h3>\n<p>For complex scenarios requiring multiple async operations, you can use <code>Promise.all()<\/code> for parallel execution or sequential await calls when order matters. Here's an example of a checkout process:<\/p>\n<pre><code class=\"language-javascript\">import wixData from 'wix-data';\nimport wixPay from 'wix-pay';\n\nasync function processCheckout(cartId) {\n    try {\n        \/\/ Step 1: Validate cart contents\n        const cart = await validateCart(cartId);\n        \n        \/\/ Step 2: Check inventory for all items in parallel\n        const inventoryChecks = cart.items.map(item => \n            checkInventory(item.productId, item.quantity)\n        );\n        \n        const inventoryResults = await Promise.all(inventoryChecks);\n        \n        \/\/ If any inventory check failed, abort checkout\n        const inventoryIssue = inventoryResults.find(result => !result.available);\n        if (inventoryIssue) {\n            return {\n                success: false,\n                error: \"inventoryIssue\",\n                productId: inventoryIssue.productId,\n                message: `Sorry, ${inventoryIssue.productName} is out of stock.`\n            };\n        }\n        \n        \/\/ Step 3: Process payment\n        const paymentResult = await processPayment(cart);\n        if (!paymentResult.success) {\n            return {\n                success: false,\n                error: \"paymentFailed\",\n                message: paymentResult.message\n            };\n        }\n        \n        \/\/ Step 4: Update inventory and create order (these must happen together)\n        const [inventoryUpdateResult, orderResult] = await Promise.all([\n            updateInventoryQuantities(cart.items),\n            createOrder(cart, paymentResult.transactionId)\n        ]);\n        \n        \/\/ Step 5: Send confirmation email (can happen after response)\n        sendOrderConfirmationEmail(orderResult.orderId)\n            .catch(error => console.error(\"Failed to send confirmation email:\", error));\n        \n        \/\/ Return success result\n        return {\n            success: true,\n            orderId: orderResult.orderId,\n            message: \"Your order has been placed successfully!\"\n        };\n    } catch (error) {\n        console.error(\"Checkout process failed:\", error);\n        return {\n            success: false,\n            error: \"systemError\",\n            message: \"An unexpected error occurred. Please try again.\"\n        };\n    }\n}\n<\/code><\/pre>\n<blockquote>\n<p>\nUsing async and await can greatly improve the readability and maintainability of your code. It allows you to write asynchronous code that looks and behaves like synchronous code, making it easier to understand and debug, while still maintaining the performance<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the world of web development, understanding how to manage asynchronous tasks is essential. This article explores the concepts of&#8230;<\/p>\n","protected":false},"author":1,"featured_media":896,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-897","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-problem-solving"],"_links":{"self":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/897"}],"collection":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/comments?post=897"}],"version-history":[{"count":2,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/897\/revisions"}],"predecessor-version":[{"id":7768,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/897\/revisions\/7768"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media\/896"}],"wp:attachment":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media?parent=897"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/categories?post=897"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/tags?post=897"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}