Чтобы "приостановить" цикл for
с помощью await
, вы должны ждать обещания. Таким образом, вы должны заставить validateJson()
возвращать обещание, которое разрешается при выполнении любых асинхронных операций внутри этой функции. Вот как async/await
работает в Javascript.
Не совсем ясно, что является или не является асинхронным в validateJson()
. Если ничто не является асинхронным, то это просто последовательное выполнение, и вам не нужны await
или обещания вообще. Javascript является однопоточным, поэтому он будет запускаться validateJson()
до тех пор, пока не будет выполнено, и цикл for
будет заблокирован до тех пор, пока не вернется validateJson()
.
Если в validateJson()
есть некоторые асинхронные операции, вы должны убедиться, что validateJson()
возвращает обещание, которое разрешается только после выполнения всех этих асинхронных операций. Тогда и только тогда вы можете использовать await
для «приостановки» цикла for
во время выполнения асинхронных операций. Чтобы помочь вам исправить validateJson()
, нам нужно больше узнать о том, что является асинхронным, а что нет, и какой интерфейс имеют асинхронные операции, чтобы знать, когда они выполнены. Затем мы могли бы помочь вам validateJson()
вернуть обещание, которое было решено в нужное время, чтобы заставить await
работать должным образом.
Кроме того, вы можете использовать await
только внутри функции, которая объявлена async
, поэтому вам также придется добавить это в определение processJson()
.
let processJson = async function(items) {
Чтобы проиллюстрировать эту концепцию, вот простой пример, который вы можете запустить прямо здесь во фрагменте кода, чтобы увидеть, как он приостанавливает цикл for
:
function delay(t) {
return new Promise(function(resolve) {
setTimeout(resolve, t);
});
}
async function run() {
console.log("starting...");
for (let i = 0; i < 10; i++) {
await delay(1000);
console.log("Timer " + i + " fired");
}
console.log("done");
}
run();
Теперь, когда вы добавили больше кода, мы можем поговорить о вашем реальном коде (хотя до сих пор неясно, что resCallback()
или processItem()
делают, так что это, возможно, еще не конец изменений.
Сначала измените maintenanceCall()
, чтобы вернуть обещание, которое я сделаю в основном, переключившись на модуль запроса-обещания и вернув это обещание:
const rp = require('request-promise');
const maintenanceCall= function (id, jsonObj, specialFlag) {
return rp.post({
url: 'https://url.poster/something',
auth: {
'user': 'user',
'pass': 'pass',
'sendImmediately': true
},
json: true,
body: {
"Input": {
"InputParameters": {
"KEY": jsonObj.key1,
"Hole": jsonObj.Key2,
"SomeWhere": jsonObj.keySpecial
}
}
}
}).then(function(body) {
if (body.OutputParameters.X_MSG_DATA !== null) {
resCallback(id + , Message: "
+ body.OutputParameters.DATA);
}
else {
// FIX THIS: You define this function here, but never use it, that's odd
const sampCheck = function(smsFlag){
if(flag=== "Y")
return ".X";
else if(flag=== "N")
return "";
else
resCallback(id + ": this item can not be processed");
processItem(id, jsonObj, stats);
}
}
});
};
Теперь, когда maintenanceCall()
возвращает обещание, вы можете использовать его в validateJson()
следующим образом, поэтому оно всегда возвращает обещание:
const validateJson = function (id, jsonObj) {
const processItemSchema = {
"properties": {
"key1": {
"type": "string"
},
"key2": {
"type": "string",
"minLength": 3,
"maxLength": 3
},
"keySpecial": {
"type": "string",
"minLength": 4,
"maxLength": 4
}
}
};
const ajv = new Ajv();
let validate = ajv.compile(processItemSchema);
let valid = validate(jsonObj);
if (!valid) {
resCallback(id + ": invalid JSON");
return Promise.reject(new Error(id + ": invalid JSON"));
} else {
// Generate Special Flag(s) value, Comma Separated Value
let specialFlag = "";
specialFlag += specialCheck1(jsonObj.keySpecial);
if(specialFlag.length > 0) {
let temp = specialCheck2(jsonObj.keySpecial);
if (temp.length > 0) {
specialCheck += "," + temp;
}
} else {
specialFlag += specialCheck1(jsonObj.keySpecial);
}
return maintenanceCall(id, jsonObj, specialFlag);
}
};
И затем вы можете вернуться к своей функции processJson()
и заставить ваш цикл for
запускать последовательно так:
let processJson = async function(items) {
for (const p in items) {
let newObj = {
"key1": items[p].key1,
"key2": items[p].key2,
"keySpecial": items[p].key3 + items[p].key4
};
await validateJson(p, newObj);
}
};
И вызывающий абонент может использовать processJson()
следующим образом:
processJson(someItems).then(() => {
console.log("all done here");
}).catch(err => {
console.log(err);
});