Метод не ждет разрешения обещания

#javascript #node.js #asynchronous

Вопрос:

У меня есть функция, которую я пытаюсь вызвать, и в основном заставляю ее ждать ответа, прежде чем перейти к следующему.

У меня есть две функции, обе асинхронные.

Первый выглядит примерно так, со всеми параметрами, которые начинаются с»_», которые будут использоваться в качестве обратных вызовов:

 async function formatJson(input, _sendToThirdParty, _handleLogs, _setDimensions)
{
     ...do some work here to format the payload
     if(onlineConnectionRequired)
    {
         _setDimensions(itemToUpdate, object);
    }
    else {
         // Do non-online based transformations here
    }
    ...do more work after the above
}
 

В принципе, исходя из этого, я пытаюсь вызвать этот метод setDimensions, который выглядит следующим образом:

 async function setDimensions(itemToUpdate, object) {
    try
    {
        if(itemToUpdate != null)
        {
            console.log("Loading dimensions");
    
            await Promise.resolve(function() {
                ns.get(`inventoryItem/${object['Item ID']}?expandSubResources=true`)
                .then((res) => {
                    console.log("Inventory Item Loaded. Updating dimensions...");

                    itemToUpdate.consignments.push(
                        {
                            consignmentID: object.conID,
                            barcode: object.barcode,
                            itemID: '', // leaving as empty for now
                            width : res.data.custitem_width,
                            length : res.data.custitem_length,
                            height : res.data.custitem_height,
                            weight : res.data.custitem_weight,
                            fragile: object.fragile === 'T' ? 1 : 0,
                            description: object.description
                        }
                    );

                    console.log("Dimensions Finalised");
                })
            });
        }
    }
    catch(err)
    {
        console.log(err);
        const message = `Error attempting to set the dimensions for ${object['Item ID']}`;
        console.log(message);
        throw new Error(message);
    }
}
 

Проблемы, с которыми я сталкиваюсь, заключаются в следующем:

  1. Код из первого метода продолжается, прежде чем ждать разрешения обещания, но мне нужно, чтобы он подождал, чтобы я мог полностью завершить создание полезной нагрузки, прежде чем он продолжит выполнение следующих битов
  2. Если я попытаюсь включить await ключевое слово перед вызовом _setDimensions(...) в первый метод, я получу ошибку «Синтаксическая ошибка: ожидание допустимо только в асинхронной функции», но я бы подумал, что это асинхронная функция?

Если бы кто-нибудь мог помочь, это было бы невероятно ценно! Спасибо!!

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

1. используйте конструктор promise не Promise.resolve

2. ns.get похоже, что я уже вернул обещание

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

4. _setDimentions Возвращает ли функция обещание? Во-вторых, await Promise.resolve() может разрешиться непосредственно перед завершением обратного вызова. Вы должны использовать new Promise() вместо этого.

5. » Я бы подумал, что это асинхронная функция? «- да, formatJson это ан async function . Пожалуйста, покажите нам точный код, который вы пробовали, без каких-либо уточнений.

Ответ №1:

Правильный дизайн ваших функций приведен ниже:

 formatJson(input, (err, value) => {
    if(err) {
        // Error handler goes here
        //console.log(err);
        throw err;
    } else {
        // Implementation for working with returned value
        console.log(value);
    }
});

function formatJson(input, callback)
{
    //...do some work here to format the payload
    if(onlineConnectionRequired)
    {

        setDimensions(itemToUpdate, object)
            .then((updatedItem) => {
                // Implement anything here to work with your
                // result coming from setDimensions() function

                //console.log(updatedItem);

                // Callback with null error and updatedItem as value
                callback(null, updatedItem);
            })
            .catch((err) => {
                // Callback with err object and null value
                callback(err, null);
            });
    }
    else {
         // Do non-online based transformations here
    }
    //...do more work after the above
}

function setDimensions(itemToUpdate, object) {
    try
    {
        if(inventoryItemID != null)
        {
            console.log("Loading dimensions");
    
            return new Promise(function(resolve, reject) {
                ns.get(`inventoryItem/${object['Item ID']}?expandSubResources=true`)
                    .then((res) => {
                        console.log("Inventory Item Loaded. Updating dimensions...");

                        itemToUpdate.consignments.push(
                            {
                                consignmentID: object.conID,
                                barcode: object.barcode,
                                itemID: '', // leaving as empty for now
                                width : res.data.custitem_width,
                                length : res.data.custitem_length,
                                height : res.data.custitem_height,
                                weight : res.data.custitem_weight,
                                fragile: object.fragile === 'T' ? 1 : 0,
                                description: object.description
                            }
                        );

                        console.log("Dimensions Finalised");

                        resolve(itemToUpdate);
                    })
                    .catch((err) => reject(err));
            });
        }
    }
    catch(err)
    {
        console.log(err);
        const message = `Error attempting to set the dimensions for ${object['Item ID']}`;
        console.log(message);
        throw new Error(message);
    }
}
 

Ошибки в вашем коде:

  1. У вашей formatJson функции было async ключевое слово, но у вашей formatJson функции были названы функции обратного _sendToThirdParty, _handleLogs, _setDimensions вызова . Существует 3 типа реализации для создания асинхронных кодов. Вы можете использовать обратные вызовы, обещания или асинхронное/ожидание. Но обещания и асинхронность/ожидание одинаковы, за исключением их вариантов использования и синтаксиса. Когда вы определяете функцию так, как async fn() {...} она в основном возвращает новое обещание, это равносильно высказыванию fn() { return new Promise(); } . Функции с обратными вызовами имеют такую форму, как function(params, callback) { callback(cbParams); } вы можете использовать функцию обратного вызова в нескольких ветвях своей функции. Но у вас есть только одна функция обратного вызова, в вашем коде было 3 функции обратного вызова. Также обратите внимание, что функции с обратным вызовом не имеют async ключевого слова. Это неверно, потому что, как я упоминал ранее, асинхронная функция вернет обещание. Поэтому вы не должны (но вы можете) определять функцию так async function(params, callback) , как вы это сделали в своем первом методе. Это определение не является неправильным, и оно может работать, но оно недействительно.
  2. Ваш второй метод был асинхронной функцией, которая ничего не возвращала. Поэтому я изменил его на нормальную функцию с возвратом обещания.

Ответ №2:

Вызывается ли formatJson метод внутри асинхронного метода? Это должно быть, и перед _setDimensions вам нужно добавить await ключевое слово. И, как сказал Дэниел, используйте конструктор обещаний.

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

1. Его не требуется использовать formatJson в асинхронной функции, вы можете использовать его как formatJson.then().catch() в обычной функции синхронизации. Ключевое слово async, добавленное перед объявлением функции, заставляет вашу асинхронную функцию возвращать обещание.