【问题标题】:TypeError: Cannot read property 'forEach' of undefined (node js, stripe, express)类型错误:无法读取未定义的属性“forEach”(节点 js、条纹、快递)
【发布时间】:2021-02-03 23:24:55
【问题描述】:

这是我第一次尝试使用node js,所以我按照教程开发了一个带条纹的node js购物车,但是我买了一些东西后出现了一些错误。我的 Stripe 账户也有支票,显然这些物品没有付款

终端中的错误信息:

C:\Users\lee hao zheng\Desktop\shopping cart(node js2)\server.js:42
            req.body.items.forEach(function(item){
                           ^

TypeError: Cannot read property 'forEach' of undefined
    at C:\Users\lee hao zheng\Desktop\shopping cart(node js2)\server.js:42:28
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)

控制台错误提示

purchase:1 Failed to load resource: net::ERR_CONNECTION_RESET

store.js:67 TypeError: Failed to fetch
(anonymous) @ store.js:67

store.js 代码

if (document.readyState == 'loading') {
    document.addEventListener('DOMContentLoaded', ready)
} else {
    ready()
}

function ready() {
    var removeCartItemButtons = document.getElementsByClassName('btn-danger')
    for (var i = 0; i < removeCartItemButtons.length; i++) {
        var button = removeCartItemButtons[i]
        button.addEventListener('click', removeCartItem)
    }

    var quantityInputs = document.getElementsByClassName('cart-quantity-input')
    for (var i = 0; i < quantityInputs.length; i++) {
        var input = quantityInputs[i]
        input.addEventListener('change', quantityChanged)
    }

    var addToCartButtons = document.getElementsByClassName('shop-item-button')
    for (var i = 0; i < addToCartButtons.length; i++) {
        var button = addToCartButtons[i]
        button.addEventListener('click', addToCartClicked)
    }

    document.getElementsByClassName('btn-purchase')[0].addEventListener('click', purchaseClicked)
}

var stripeHandler =StripeCheckout.configure({
key: stripePublicKey,
locale:'en',
token:function(token){
        var items=[]
        var cartItemContainer= document.getElementsByClassName('cart-items')[0]
        var cartRows= cartItemContainer.getElementsByClassName('cart-row')
        for (var i=0; i < cartRows.length; i++){
            var cartRow = cartRows[i]
            var quantityElement = cartRow.getElementsByClassName('cart-quantity-input')[0]
            var quantity= quantityElement.value
            var id= cartRow.dataset.itemId
            items.push({
                id:id,
                quantity: quantity
            })
        }

        fetch('/purchase', {
            method:'POST',
            header:{
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            },
            body: JSON.stringify({
                stripeTokenId: token.id,
                items: items
            })
        }).then(function(res){
            return res.json()
        }).then(function(data){
            alert(data.message)
            var cartItems = document.getElementsByClassName('cart-items')[0]
            while (cartItems.hasChildNodes()) {
                cartItems.removeChild(cartItems.firstChild)
            }
            updateCartTotal()
        }).catch(function(error){
            console.error(error)
        })
    }   
})

function purchaseClicked() {
    // alert('Thank you for your purchase')
   
    var priceElement =document.getElementsByClassName('cart-total-price')[0]
    var price= parseFloat(priceElement.innerText.replace('$', ''))*100
    stripeHandler.open({
        amount: price
    })
}

function removeCartItem(event) {
    var buttonClicked = event.target
    buttonClicked.parentElement.parentElement.remove()
    updateCartTotal()
}

function quantityChanged(event) {
    var input = event.target
    if (isNaN(input.value) || input.value <= 0) {
        input.value = 1
    }
    updateCartTotal()
}

function addToCartClicked(event) {
    var button = event.target
    var shopItem = button.parentElement.parentElement
    var title = shopItem.getElementsByClassName('shop-item-title')[0].innerText
    var price = shopItem.getElementsByClassName('shop-item-price')[0].innerText
    var imageSrc = shopItem.getElementsByClassName('shop-item-image')[0].src
    var id = shopItem.dataset.itemId
    addItemToCart(title, price, imageSrc, id)
    updateCartTotal()
}

function addItemToCart(title, price, imageSrc,id) {
    var cartRow = document.createElement('div')
    cartRow.classList.add('cart-row')
    cartRow.dataset.itemId = id
    var cartItems = document.getElementsByClassName('cart-items')[0]
    var cartItemNames = cartItems.getElementsByClassName('cart-item-title')
    for (var i = 0; i < cartItemNames.length; i++) {
        if (cartItemNames[i].innerText == title) {
            alert('This item is already added to the cart')
            return
        }
    }
    var cartRowContents = `
        <div class="cart-item cart-column">
            <img class="cart-item-image" src="${imageSrc}" width="100" height="100">
            <span class="cart-item-title">${title}</span>
        </div>
        <span class="cart-price cart-column">${price}</span>
        <div class="cart-quantity cart-column">
            <input class="cart-quantity-input" type="number" value="1">
            <button class="btn btn-danger" type="button">REMOVE</button>
        </div>`
    cartRow.innerHTML = cartRowContents
    cartItems.append(cartRow)
    cartRow.getElementsByClassName('btn-danger')[0].addEventListener('click', removeCartItem)
    cartRow.getElementsByClassName('cart-quantity-input')[0].addEventListener('change', quantityChanged)
}

function updateCartTotal() {
    var cartItemContainer = document.getElementsByClassName('cart-items')[0]
    var cartRows = cartItemContainer.getElementsByClassName('cart-row')
    var total = 0
    for (var i = 0; i < cartRows.length; i++) {
        var cartRow = cartRows[i]
        var priceElement = cartRow.getElementsByClassName('cart-price')[0]
        var quantityElement = cartRow.getElementsByClassName('cart-quantity-input')[0]
        var price = parseFloat(priceElement.innerText.replace('$', ''))
        var quantity = quantityElement.value
        total = total + (price * quantity)
    }
    total = Math.round(total * 100) / 100
    document.getElementsByClassName('cart-total-price')[0].innerText = '$' + total
}

这是要运行的文件,server.js

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
    // require('dotenv').load()
}

const stripeSecretKey = process.env.STRIPE_SECRET_KEY
const stripePublictKey = process.env.STRIPE_PUBLIC_KEY

console.log(stripeSecretKey,stripePublictKey)

const express= require('express')
const app =express()
const fs=require('fs')
const stripe = require('stripe')(stripeSecretKey)

app.set('view engine', 'ejs')
app.use(express.json())
app.use(express.static('public'))

app.get('/store.html',function(req, res){
    fs.readFile('items.json', function(error,data){
        if(error){
            res.status(500).end()
        }else{
            res.render('store.ejs',{
                stripePublicKey: stripePublictKey,
                items: JSON.parse(data)
            })
        }
    })
})

app.post('/purchase',function(req, res){
    fs.readFile('items.json', function(error,data){
        if(error){
            res.status(500).end()
        }else{
           
            const itemsJson = JSON.parse(data)
            const itemsArray = itemsJson.music.concat(itemsJson.merch)
            let total = 0;
            req.body.items.forEach(function(item){
                const itemJson = itemsArray.find(function(i){
                    return i.id == item.id
                })
                total = total + itemJson.price* item.quantity
            })
            stripe.charges.create({
                amount: total,
                source: req.body.stripeTokenId,
                currency:'usd'
            }).then(function(){
                console.log('Charge Successful')
                res.json({message: 'Successfully purchased items'})
            }).catch(function(){
                console.log('Charge Fail')
                res.status(500).end()
            })
        }
    })
})
app.listen(3000)

store.ejs

<!DOCTYPE html>
<html>
    <head>
        <title>The Generics | Store</title>
        <meta name="description" content="This is the description">
        <link rel="stylesheet" href="styles.css" />
        <script src="https://checkout.stripe.com/checkout.js" defer></script>
        <script>
            var stripePublicKey = '<%= stripePublicKey %>'
        </script>
        <script src="store.js" defer></script>
    </head>
    <body>
        <header class="main-header">
            <nav class="main-nav nav">
                <ul>
                    <li><a href="index.html">HOME</a></li>
                    <li><a href="store.html">STORE</a></li>
                    <li><a href="about.html">ABOUT</a></li>
                </ul>
            </nav>
            <h1 class="band-name band-name-large">The Generics</h1>
        </header>
        <section class="container content-section">
            <h2 class="section-header">MUSIC</h2>
            <div class="shop-items" >
                <% items.music.forEach(function(item){%>

                    <div class="shop-item"  data-item-id="<%= item.id%>">
                        <span class="shop-item-title"><%= item.name%></span>
                        <img class="shop-item-image" src="Images/<%= item.imgName%> ">
                        <div class="shop-item-details">
                            <span class="shop-item-price">$<%= item.price/100 %> </span>
                            <button class="btn btn-primary shop-item-button" type="button">ADD TO CART</button>
                        </div>
                    </div>
           <% }) %>              
             </div> 
        </section>
        <section class="container content-section">
            <h2 class="section-header">MERCH</h2>
                <div class="shop-items">
                <% items.merch.forEach(function(item){%>

                <div class="shop-item"  data-item-id="<%= item.id%>">
                    <span class="shop-item-title"><%= item.name%></span>
                    <img class="shop-item-image" src="Images/<%= item.imgName%> ">
                    <div class="shop-item-details">
                        <span class="shop-item-price">$<%= item.price/100 %> </span>
                        <button class="btn btn-primary shop-item-button" type="button">ADD TO CART</button>
                    </div>
                </div>
                <% }) %>  
                </div>
        </section>
        <section class="container content-section">
            <h2 class="section-header">CART</h2>
            <div class="cart-row">
                <span class="cart-item cart-header cart-column">ITEM</span>
                <span class="cart-price cart-header cart-column">PRICE</span>
                <span class="cart-quantity cart-header cart-column">QUANTITY</span>
            </div>
            <div class="cart-items">
            </div>
            <div class="cart-total">
                <strong class="cart-total-title">Total</strong>
                <span class="cart-total-price">$0</span>
            </div>
            <button class="btn btn-primary btn-purchase" type="button">PURCHASE</button>
        </section>
        <footer class="main-footer">
            <div class="container main-footer-container">
                <h3 class="band-name">The Generics</h3>
                <ul class="nav footer-nav">
                    <li>
                        <a href="https://www.youtube.com" target="_blank">
                            <img src="Images/YouTube Logo.png">
                        </a>
                    </li>
                    <li>
                        <a href="https://www.spotify.com" target="_blank">
                            <img src="Images/Spotify Logo.png">
                        </a>
                    </li>
                    <li>
                        <a href="https://www.facebook.com" target="_blank">
                            <img src="Images/Facebook Logo.png">
                        </a>
                    </li>
                </ul>
            </div>
        </footer>
    </body>
</html>

【问题讨论】:

  • 我建议你做console.log(req.body) 看看它到底是什么。显然req.body.items 不是您认为的数组。

标签: javascript node.js express stripe-payments


【解决方案1】:

建议——不要盲目启动node js。首先从 javascript 的基本概念开始,例如回调、promise 和异步。

我认为不是这个

req.body.items.forEach(function(item){

你需要写

data.items.forEach(function(item){

【讨论】:

  • 试试 itemsArray.forEach(...)
  • 控制台现在显示此错误purchase:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error) 第二个控制台错误:store.js:67 SyntaxError: Unexpected end of JSON input at store.js:58 (anonymous) @ store.js:67 终端现在显示此输出:PS C:\Users\lee hao zheng\Desktop\shopping cart(node js2)&gt; node server.jsde server.js Charge Fail
  • 检查你的 json 文件,或者尝试从文件中导出一个 json 对象,否则你的代码看起来很干净
  • 如何从其他文件导出json对象?
  • 首先创建一个变量 var json = {...here is your json data} 然后从该文件中执行 module.exports = {json : json} 现在您可以在必要时使用它。确保将文件保存为 .js
猜你喜欢
  • 2017-11-01
  • 2022-11-21
  • 2018-07-12
  • 1970-01-01
  • 1970-01-01
  • 2021-07-19
  • 2021-01-17
  • 2020-09-25
  • 1970-01-01
相关资源
最近更新 更多