Обратный вызов без эффекта, функция все еще выполняется перед обратным вызовом - PullRequest
0 голосов
/ 23 октября 2019

У меня есть функция с обратным вызовом, моя проблема в том, что возврат функции происходит до объявления обратного вызова, а затем возвращает ноль вместо того, чтобы возвращать мне массив координат

function callback(coordinates=[]){
    console.log(coordinates);
    return coordinates;
}
 function getCoordinates(callback){
    connection.connect();
    let coordinates=[null];
    connection.query('SELECT AreaId AS areaNumber, longitude AS longitude, latitude AS latitude FROM coordinates', function (error, results, fields) {
        if (error) throw error;
        let area=[];
        for (result of results) {
            if (!area.includes(result.areaNumber)){
                area.push(result.areaNumber)
                coordinates[result.areaNumber]=[];
            }
            coordinate=[result.longitude,result.latitude];
            coordinates[result.areaNumber].push(coordinate);
        }    
        coordinates=callback(coordinates)
    });
    connection.end();
    return coordinates;
}
console.log(getCoordinates(callback));

, и у меня есть:

[null] // соответствует console.log (getCoordinates (callback));

и

[массив со значением] // соответствует console.log (координаты) в функции vallback

Как это сделать длячто мой обратный вызов будет рассмотрен?
Извините, я новичок в node.js, поэтому я мог неправильно понять обратный вызов. То, что я хотел бы получить массив координат, которые я могу использовать позже в 2 разных местах в моем коде, как:

.get('/map', function(req, res) {
    let Coords=getCoordinate(callback)
    res.render('map.ejs', {token: tokenMapbox, coordinates: Coords});
})
.get('/wmap', function(req, res) {
    let Coords=getCoordinate(callback)
    res.render('wmap.ejs', {token: tokenMapbox, coordinates: Coords});
})

Ответы [ 2 ]

1 голос
/ 23 октября 2019

Существует несколько подходов к этой проблеме, однако, если вы хотите использовать полученные координаты аналогично синхронному коду, я предлагаю вам попробовать использовать синтаксис async / await. Если вы вызываете свой запрос из асинхронной функции, вы можете использовать ключевое слово await , чтобы обеспечить более читаемый код.

Как только ваша переменная координат будет заполнена в вашей асинхронной функции, вы можете делать то, что вы хотитес ним.

Например:

function getCoordinates() {
    connection.connect();
    let coordinates = [];
    return new Promise((resolve, reject) => {
        connection.query('SELECT AreaId AS areaNumber, longitude AS longitude, latitude AS latitude FROM coordinates', function (error, results, fields) {
            if (error) {
                reject(error);
            } else {
                let area=[];
                for (result of results) {
                    if (!area.includes(result.areaNumber)){
                        area.push(result.areaNumber)
                        coordinates[result.areaNumber]=[];
                    }
                    coordinate=[result.longitude,result.latitude];
                    coordinates[result.areaNumber].push(coordinate);
                }    
                resolve(coordinates);
                connection.end();
            }
        });
    })
}

async function testCoordinates() {
    let coordinates = await getCoordinates();
    console.log("Coordinates:", coordinates);
    // You can do whatever you wish with the coordinates variable
}

testCoordinates();
1 голос
/ 23 октября 2019

Вы путаете разные вещи. Позвольте мне объяснить

Прежде всего, забудьте о термине «обратный вызов». Мы поймем это просто как функцию, переданную в качестве параметра другой функции. Не беспокойтесь об этом, я собираюсь объяснить.

Итак, мы начнем с проблемы: как извлечь массив координат из базы данных и напечатать его

Следующее, что вы узнаете о взаимодействии с базой данных и предположите, что именно так работает ваша библиотека: она имеет функцию connection.query(myQuery, someFunction), которая может получать результаты из базы данных.

Теперь первое, что вы заметили в этой функции запроса, это ее параметры. myQuery - это строка, а someFunction - определение функции. В то время как в других языках мы видели, что такие значения, как числа, строки и т. Д., Передаются в функцию в качестве параметров, интересно, что в javascript вы также можете передать определение функции в качестве параметра. И это то, что делает JavaScript мощным, вы можете передать определение функции в качестве параметра.

Ух ты, передача функции в качестве параметра, но как это работает? Давайте возьмем другой пример;допустим, я хочу создать функцию, которая будет выполнять некоторые вычисления

//Here myVar is a variable and doSomething is a function
function interestingJsFunction(myVar, doSomething){
   var twiceOfVar = 2*myVar;
   doSomething(twiceOfVar);
   var thriceOfVar = 3*myVar;
   doSomething(thriceOfVar);
}

Так что же делает эта функция? Он применяет некоторые вычисления и вызывает функцию doSomething в некоторых точках;в какой-то момент он передает дважды значение myVar для работы, а в один момент он проходит трижды myVar. Но то, что делает эта функция doSomething, не определено на данный момент. И вы можете определить его, передав свою функцию в качестве параметра. Это дает вам бесконечные возможности. Как?

interestingJsFunction(2, function(result){ console.log(result) })
interestingJsFunction(2, function(result){ console.log("the new behaviour" + result) })
//And so on...

Вы понимаете, как это сделало одну интересную функцию полезной в разных случаях. Если бы вы знали, что вам понадобится только одна реализация doSomething (), вы могли бы просто удалить doSomething из параметров, и все, что вы хотели сделать, вы могли бы сделать это непосредственно внутри интересующей функции (например, console.log (doubleOfVar))

Теперь вернемся к функции query. Это также интересная функцияJsFunction, и если вы перейдете к определению функции query (вы можете найти код своей библиотеки, чтобы увидеть, что находится внутри функции запроса), вы обнаружите, что она выполняет некоторые операции с базой данных, получает результаты и вызываетфункция [аналогично doSomething], которая была передана в качестве параметра, если при этом она получает какую-либо ошибку, она вызывает функцию в параметре и передает ей ошибку.

Когда он это делает, он возвращает ошибку, результаты и поле в качестве параметра этой функции. Так что теперь вы можете использовать эти параметры в вашей функции, которая была передана в качестве параметра. Теперь вам решать, как вы хотите использовать это, возможно, вы можете просто напечатать результаты следующим образом (помните, как мы использовали интересноJsFunction?)

//We could simply print the results if there are any
connection.query(myQuery, function(error, results, fields){ 
    if(results) console.log(results.toString()) 
})

//Or we could throw erorr if there's any
connection.query(myQuery, function(error, results, fields){ 
    if(error) throw error 
})

//Guess what would happen when you return something inside this function?
var myQueryFunction = connection.query(myQuery, function(error, results, fields){ 
    return "return of query function"
})


//And guess what would happen when you have something like this
function myNewFunction(){
    var x = connection.query(myQuery, function(error, results, fields){ 
        return "return of query function"
    })
    return "return of myNewFunction"
}

Я оставляю последние 2 упражнения для вас, и вы должныбыть в состоянии решить проблемы после этого. Попробуйте операторы console.log, чтобы понять

...