如何在 nodejs/knexjs 中停止异步数据库调用

How to stop asynchronous database calls in nodejs/knexjs

我想说的是,上周我一直被这个问题困扰。 我正在尝试将锻炼添加到我的数据库中,并且我从前端收到了 3 件事:作为字符串的锻炼名称,一个名为 exercises 的数组,其中包含该锻炼中每个锻炼的对象。最后,一个名为 sets 的数组是一个二维数组,每个数组包含每个集合的对象

    const exercises = [
        {name: ''}
    ]

    const sets = [
        [
            {
                reps: '',
                kg: ''
            }
        ]
    ]

我正在使用 knex,我想将这些数据插入到我的数据库中。这是我的代码:

    app.post('/newworkout', (req, res) => {
        const {workoutName, exercises, sets} = req.body;
        const loggedSets = [];
        let haveRoutinesFinished = false;
        let haveExercisesFinished = false;

        PushRoutinesToDB = () => {
            db('routines')
                .returning('id')
                .insert({
                    userid: user.id,
                    name: workoutName
                })
                .then(routineID => {
                    workoutInfo.routineID =  routineID[0];
                    haveRoutinesFinished = true;
                    console.log('1')
                    return db('loggedroutines')
                        .insert({ 
                            userid: user.id,
                            routineid: workoutInfo.routineID,
                            routinedate: new Date() 
                        })
                })
        }
        
        PushExercisesToDB = () => {
            exercises.map(exercise => {
            console.log('2')
            db('exercises')
                .insert({
                    userid: user.id,
                    routineid: workoutInfo.routineID,
                    name: exercise.name
                })
                .returning('id')
                .then(exerciseID => {
                    console.log('exercise id', exerciseID)
                    exerciseIDArray.push(exerciseID[0])
                    console.log("exerciseIDArray", exerciseIDArray)
                    haveExercisesFinished = true;
                    return db('loggedexercises')
                        .insert({
                            userid: user.id,
                            routineid: workoutInfo.routineID,
                            exerciseid: exerciseID[0]
                        })
                })
            })
            
        }
            
        PushSetsToDB = () => {
            sets.map((setsArray, i) => {
                setsArray.map(set => {
                    loggedSets.push({
                        userid: user.id,
                        routineid: workoutInfo.routineID,
                        exerciseid: exerciseIDArray[i],
                        reps: set.reps,
                        kg: set.kg
                    })
                })
            })
            console.log(loggedSets)
        
            db('loggedsets').insert(loggedSets)
        }

        PushRoutinesToDB()
        console.log(haveRoutinesFinished)
        if (haveRoutinesFinished === true) {
            PushExercisesToDB()
        }

        if (haveExercisesFinished === true) {
            PushSetsToDB()
        }

    })

代码本身可以工作,但是由于第一个数据库调用是异步的,所以第二个不工作,它依赖于第一个。我尝试使用回调来解决这个问题,但这只会导致我的代码无法 运行。有什么想法吗?

由于您的函数是 Asynchronous 即使第一个函数尚未完成,线程也会继续。

使用async/await一定能解决你的问题。

注意评论以查看更改

    app.post('/newworkout', async (req, res) => { //asynchronous Function
        const {workoutName, exercises, sets} = req.body;
        const loggedSets = [];
        let haveRoutinesFinished = false;
        let haveExercisesFinished = false;

        PushRoutinesToDB = async () => { //asynchronous Function
            db('routines')
                .returning('id')
                .insert({
                    userid: user.id,
                    name: workoutName
                })
                .then(routineID => {
                    workoutInfo.routineID =  routineID[0];
                    haveRoutinesFinished = true;
                    console.log('1')
                    return db('loggedroutines')
                        .insert({ 
                            userid: user.id,
                            routineid: workoutInfo.routineID,
                            routinedate: new Date() 
                        })
                })
        }
        
        PushExercisesToDB = async () => { //asynchronous Function
            exercises.map(exercise => {
            console.log('2')
            db('exercises')
                .insert({
                    userid: user.id,
                    routineid: workoutInfo.routineID,
                    name: exercise.name
                })
                .returning('id')
                .then(exerciseID => {
                    console.log('exercise id', exerciseID)
                    exerciseIDArray.push(exerciseID[0])
                    console.log("exerciseIDArray", exerciseIDArray)
                    haveExercisesFinished = true;
                    return db('loggedexercises')
                        .insert({
                            userid: user.id,
                            routineid: workoutInfo.routineID,
                            exerciseid: exerciseID[0]
                        })
                })
            })
            
        }
            
        PushSetsToDB = async () =>  {  //asynchronous Function
            sets.map((setsArray, i) => {
                setsArray.map(set => {
                    loggedSets.push({
                        userid: user.id,
                        routineid: workoutInfo.routineID,
                        exerciseid: exerciseIDArray[i],
                        reps: set.reps,
                        kg: set.kg
                    })
                })
            })
            console.log(loggedSets)
        
            db('loggedsets').insert(loggedSets)
        }

    // Now your all functions are asynchronous You can call them in series with 'await'

    await PushRoutinesToDB()
    await PushExercisesToDB()
    await PushSetsToDB()
    })