Почему fetch работает здесь только тогда, когда я добавляю предупреждение в конец строки? Экспресс NodeJS Выборка. Что здесь можно исправить

#javascript #node.js #express #fetch

Вопрос:

Я использую NodeJS w/ Express для создания веб-приложения, которое записывает ваш звук с помощью библиотеки VMSG и отправляет звук большого двоичного объекта в мою файловую систему с помощью HTTP-запросов и многопоточности. Он также добавляет этот экземпляр записи в базу данных MongoDB.

У меня проблема с командой fetch. Это не сработает, если я не отправлю предупреждение сразу после извлечения. Способ, которым я его настроил, заключается в том, что у меня есть мое основное экспресс-приложение (index.js), и маршрутизатор к каталогу /recordingsDirectory (recordings.js) , которая является конечной точкой для обработки сообщений. Моя основная индексная HTML-страница использует рули и использует отдельный JS-скрипт (recorder.js) для 1) использования библиотеки VMSG и 2) получения ЗАПИСИ в каталог /Recordings, как только кто-то отправит аудиофайл с именем и присутствующим аудиоблоком. Вот где я застрял. Я могу принести в recorder.js с предупреждающей строкой после выборки, но я не могу получить выборку в конце блока else if сам по себе. Я бы хотел сделать это без этого, так как предупреждение уродливое. Решение, которое я пробовал, заключается в том, что я попытался сделать функцию onsubmit асинхронной и ожидающей выборки, так как я думал, что, возможно, она ждет обещания, но это не сработало.

Вот файлы. Я прокомментировал КРИТИЧЕСКИЕ и СВЕРХКРИТИЧНЫЕ строки кода, которые вы должны проверить, и я думаю, в чем заключаются проблемы:

index.js

  const express = require('express')
    const handlebars = require('express-handlebars')
    const path = require('path')
    const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest
    const xhr = new XMLHttpRequest()
    const db = require('./db')

const app = express()

const PORT = process.env.PORT || 8000

app.set('view engine', 'hbs')

app.engine('hbs', handlebars({
    layoutsDir: path.join(__dirname, 'views', 'layouts'),
    extname: 'hbs',
    defaultLayout: 'index',
    partialsDir: path.join(__dirname, 'views', 'partials'),
}))

app.use(express.json())

app.use(express.urlencoded({extended: false}))

app.use((err, req, res, next) => {
  if (err instanceof SyntaxError amp;amp; err.status === 400 amp;amp; 'body' in err) {
      return res.status(400).send({ status: 404, message: err.message })
  }
  next()
})

app.get('/', (req, res) => {
  res.render('main', {
      title: 'Main Page'
  })
})

app.get('/recordings', (req, res) => {
  var database = db.get().db('AudioJungle')
  database.collection('recordings').find().sort({ "date": -1 }).toArray(function(err,       docs) {
    res.render('recordings', {
      title: 'Recordings',
      recordings: docs
    })
  })
})

// CRITICAL
app.use('/recordingsDirectory', require('./recordings/recordings'))

app.use(express.static('public'))

app.use('/scripts', express.static(path.join(__dirname, 'node_modules', 'vmsg')))

db.connect(function(err) {
  if (err) {
    console.log('Unable to connect to Mongo.')
    process.exit(1)
  } else {
    app.listen(PORT, () => console.log(`Listening on Port: ${PORT}`))
  }
})

process.on('SIGINT', function() {
  db.close(function () {
    console.log('Disconnected on app termination');
    process.exit(0);
  });
});

app.use((req, res, next) => {
  res.status(404).send({
      status: 404,
      error: 'Not found'
    })
})
 

recordings.js (Aka the /recordingsDirectory endpoint for a fetch POST)

 const express = require('express')
const router = express.Router()
const multer = require('multer')
const fs = require('fs-extra')
const db = require('../db')
const { ObjectId } = require('bson')
const moment = require('moment')

const upload = multer({
    storage: multer.diskStorage({
        destination: (req, file, callback) => {
            let path = './public/uploads'
            fs.mkdirsSync(path)
            callback(null, path)
        },
        filename: (req, file, callback) => {
            createRecording(req).then((id) => {
                var file_name = id   '.mp3'
                callback(null, file_name)
            })
        }
    })
})

var type = upload.single('audio-file')

// CRITICAL
router.post('/', type, (req, res) => {
    console.log('made it')
    res.status(200)
    res.send('OK')
})

router.delete('/delete', (req, res) => {
    deleteRecording(req.body._id).then((dbResponse) => {
        if (dbResponse == null || dbResponse == undefined) {
            res.status(400).json({ msg: 'ID already deleted' })
        } else {
            res.status(200)
        }
    })
})

router.get('/', (req, res) => {
    var database = db.get().db('AudioJungle')
    var recordings = database.collection('recordings')
    recordings.findOne({"_id": ObjectId(req.query.id)}, function(err, result) {
        if (err) throw err

        if (result == null || result == undefined) {
            return res.status(400).json({
                status: 404,
                error: 'Recording no longer in the database'
            })
        }
        res.status(200)
        res.json({
            name: result.name,
            date: result.date
        })
    })
})

async function createRecording(req) {
    var database = db.get().db('AudioJungle')
    var recordings = database.collection('recordings')
    var audioObject = {
        name: req.body.name,
        date: moment().format('MMMM Do YYYY, h:mm:ss a')
    }

    var dbResponse = await recordings.insertOne(audioObject)
    return dbResponse.insertedId
}

async function deleteRecording(id) {
    var database = db.get().db('AudioJungle')
    var recordings = database.collection('recordings')
    var audioToDelete = {
        _id: ObjectId(id)
    }

    var deleteResult = await recordings.deleteOne(audioToDelete)
    return deleteResult
}

module.exports = router
 

And below is the Script the audio and name and tries to Fetch (where I need the alert for it to actually process into the /recordingsdirectory)

recorder.js

 import { record } from "/scripts/vmsg.js";

let recordButton = document.getElementById("record");

var blobObj = null

recordButton.onclick = function() {
  record({wasmURL: "/scripts/vmsg.wasm"}).then(blob => {
    blobObj = blob
    
    var tag = document.createElement("p")
    tag.id="finishedRecording"
    var text = document.createTextNode("Audio File Recorded")
    tag.appendChild(text)
    var element = document.getElementById("box")
    element.appendChild(tag)
    document.getElementById('box').appendChild(a)
  })
}

let form = document.getElementById('mp3Form');

form.addEventListener("submit", submitAudio) 

function submitAudio() {
  var fileName = form.elements[0].value

  if (fileName == "") {
    alert('Please enter a name for your file')
  } else if (blobObj != null) {
  // CRITICAL
  // SUPER CRITICAL WHERE FETCH DOESN'T WORK UNLESS I PUT AN ALERT AT THE END
    const formData = new FormData()
    formData.append('name', fileName) 
    formData.append('audio-file', blobObj)
    
    const options = {
      method: 'POST',
      body: formData
    }

    fetch('/recordingsDirectory', options);
    // If I comment an alert here, /recordingsDirectory will process the post since it console.logs 'made it'
  } else {
    alert('Record some Audio to upload')
  }
}
 

Вот моя файловая система.

введите описание изображения здесь

Кроме того, я хотел бы отметить, что функция извлечения работает должным образом на моем ПК с Windows без необходимости добавлять предупреждение, но она не работает без предупреждения на моем MacBook. Если кто-нибудь обнаружит исправление или ошибку в том, как я делаю это, пожалуйста, дайте мне знать. Я застрял на этой проблеме уже целый день. Огромное спасибо!

Комментарии:

1. Вам необходимо запретить процесс отправки формы по умолчанию. Предупреждение просто блокирует его

2. @charlietfl Милая! Это решило проблему, но могу ли я спросить, что именно делает preventDefault для решения этой проблемы? Я совершенно не понимаю, как это все исправляет.

3. Когда вы добавляете прослушиватель событий отправки, он запускается до того, как произойдет окончательная отправка, если вы не предотвратите использование по умолчанию. Браузер отправит форму внутренне по action URL-адресу формы или текущему URL-адресу, если никаких действий не существует. Предотвращение остановок по умолчанию, которые