Проблема с асинхронной обработкой nodejs

Я работаю над приложением nodejs, используя грозный сторонний модуль. И я пытаюсь получить доступ к глобальной области видимости (см. Var formfields ниже) к полям веб-формы, возвращаемым методом form.parse ниже. Во-первых, form.parse - это асинхронная операция, и согласно документации модуля здесь: https://github.com/felixge/node-formidable предназначен для обратного вызова. Я делаю это, см. Анонимную функцию, переданную в form.parse.

Моя проблема в том, что независимо от того, что я делаю, я не могу заставить form.parse правильно возвращать объект полей в переменную formfields в глобальном контексте / области. Я пробовал (в течение нескольких дней) различные комбинации функций обратного вызова и замыканий, которые возвращают вторичные функции и т. Д. Но не повезло.

Основное, что я пытаюсь сделать, это:

var form = new formidable.IncomingForm();
form.encoding = 'utf-8';
var formfields = form.parse(req, function (err, fields, files) {
  console.log("within form.parse method, subject field of fields object is: " + fields.subjects);
  return fields;
}); // form.parse

console.log("type of formfields is: " + typeof formfields);
console.log("subject field of formfields object is: " + formfields.subjects);

Но, как вы увидите из вывода console.log ниже, несмотря на то, что я использую обратный вызов, выполнение "переходит" в последние 2 строки кода console.log - перед запуском строки console.log в форме .parse или правильное возвращение "полей" из form.parse и присвоение его 'var formfields'.

В частности, вывод console.log показывает, что form.parse возвращает объект (поля), которые становятся полями формы. Но в нем отсутствуют фактические данные формы (например, formfields.subjects), которые регистрируются как неопределенные. Последняя строка вывода показывает, что form.parse захватывает данные формы (fields.subjects, которые регистрируются как «биология»), но не возвращает их должным образом, чтобы они стали «var formfields».

type of formfields is: object
subject field of formfields object is: undefined
within form.parse method, subject field of fields object is: biology

У меня нет решения этой проблемы, поскольку у меня есть возможность просто получить доступ к данным поля и управлять ими из form.parse. Но у меня есть разные вещи, связанные с этими данными формы (запрос базы данных, форматирование результатов, возврат клиенту), и все они должны быть вложены в form.parse. Это выполнимо, но создает неудобный код. Я надеялся на решение своего вопроса, поскольку это сделает код более чистым. Спасибо заранее за любую помощь.


person PaulE    schedule 03.12.2018    source источник
comment
Ваш вопрос слишком длинный, и подумайте о том, чтобы прочитать минимальный воспроизводимый пример   -  person Rarblack    schedule 03.12.2018
comment
Либо обрабатывайте его синхронно без обратного вызова, либо консольируйте свои журналы внутри функции обратного вызова.   -  person HOTAM SINGH    schedule 03.12.2018


Ответы (1)


Вы видите базовое поведение асинхронного JavaScript. Похоже, вы знаете об этом, но на всякий случай, если это вообще сбивает с толку, я предлагаю вам прочитать об этом. Обычного поиска в Google по запросу «асинхронность javascript, обратные вызовы и обещания» может быть достаточно.

Теперь к утверждению:

Это выполнимо, но создает неудобный код.

Я предполагаю, что в некотором смысле это неудобно, но так было примерно 10 лет назад, до того, как Promises были введены jQuery, а затем изначально ES2015 и позже превзошли async методы.

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

async function yourFunction() {
    var form = new formidable.IncomingForm();
    form.encoding = 'utf-8';
    var formfields = await new Promise(function (resolve, reject) {
        form.parse(req, function (err, fields, files) {
            if (err) {
                reject(err);
                return;
            }
            console.log("within form.parse method, subject field of fields object is: " + fields.subjects);
            resolve(fields);
        }); // form.parse
    });

    console.log("type of formfields is: " + typeof formfields);
    console.log("subject field of formfields object is: " + formfields.subjects);
}

Это заставит скрипт приостановиться до завершения синтаксического анализа. Вызов функции resolve(fields) гарантирует, что вашей переменной formFields будет присвоено значение объекта fields. Затем сценарий возобновится, и в ваших журналах будет напечатано то, что вы от них ожидаете.

Обратите внимание, что это не меняет способ работы JS, и по-прежнему происходит асинхронный вызов.

Также обратите внимание, что это не будет работать изначально на NodeJS, поэтому вы должны контролировать свою среду, так как вам нужно будет выполнить некоторую транспиляцию Babel. Основываясь на вашем стиле кодирования, я могу предположить, что вы не обязательно знаете обо всем этом. Если это правда, вы можете прочитать о новых сценариях ECMAS и о том, как работать с новыми функциями.

person Avius    schedule 04.12.2018
comment
Ваше решение отлично работает даже в моей среде Nodejs. Я ценю помощь. - person PaulE; 06.12.2018
comment
что, если я захочу сделать что-то вроде этого потом: form.on('file', (name,file)=> {}) После выполнения обещания эта инструкция не будет выполнена. что может быть причиной этого? - person user 007; 09.04.2019
comment
Сказать почти невозможно, поскольку это полностью зависит от контекста - где вы хотите это сделать и каков ожидаемый результат. Если вы вставите фрагмент кода, я смогу указать на проблему и предложить решение. - person Avius; 10.04.2019