#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);
}
}
Проблемы, с которыми я сталкиваюсь, заключаются в следующем:
- Код из первого метода продолжается, прежде чем ждать разрешения обещания, но мне нужно, чтобы он подождал, чтобы я мог полностью завершить создание полезной нагрузки, прежде чем он продолжит выполнение следующих битов
- Если я попытаюсь включить
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);
}
}
Ошибки в вашем коде:
- У вашей
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:
Вызывается ли formatJson
метод внутри асинхронного метода? Это должно быть, и перед _setDimensions вам нужно добавить await
ключевое слово. И, как сказал Дэниел, используйте конструктор обещаний.
Комментарии:
1. Его не требуется использовать
formatJson
в асинхронной функции, вы можете использовать его какformatJson.then().catch()
в обычной функции синхронизации. Ключевое слово async, добавленное перед объявлением функции, заставляет вашу асинхронную функцию возвращать обещание.