Весь смысл асинхронных API в том, что вы не можете писать
data = getResultsAsynchronously();
doStuffWith(data);
...
(Если вы не используете await
, что немного волшебно.)
Вместо этого традиционные асинхронные API-интерфейсы принимают функцию для вызова, когда результат готов:
getResultsAsynchronously(function (data) {
doStuffWith(data);
...
});
т.е. весь код, который следует за исходным вызовом функции в синхронной версии, вместо этого помещается в функцию обратного вызова и передается в getResultsAsynchronously
.
Обещания по-прежнему следуют этому общему шаблону, но позволяют отделить, начиная саму асинхронную операцию, от решения, как обрабатывать результат. То есть вы можете сначала запустить асинхронную операцию и зарегистрировать обратный вызов, который обрабатывает результаты позже, на втором шаге:
promise = getResultsAsynchronously();
// and later:
promise.then(function (data) {
doStuffWith(data);
...
});
Однако вам не нужно разделять два шага, если вы не хотите:
getResultsAsynchronously().then(function (data) {
doStuffWith(data);
...
});
.then
также возвращает обещание, к которому вы можете прикрепить дополнительные обратные вызовы, позвонив по номеру .then
или .catch
.
В вашем коде
data = jq.run(filter, jsonPath).then(...).catch(...)
data
- это просто еще одно обещание, но без какого-либо полезного возвращаемого значения (потому что ваши обратные вызовы then
и catch
не возвращают никакого значения).
Чтобы исправить вашу логику, она должна выглядеть так:
jq.run(filter, jsonPath).then((data) => {
fs.appendFile('./jqTest.txt', data + "\r\n", (err) => {
if (err) throw err;
console.log("complete!")
});
}).catch((err) => {
console.error(err)
});
Напомним: асинхронные результаты доступны только внутри функций обратного вызова. Вы не можете использовать возвращаемое значение, как при синхронной операции.
Тем не менее, async
/ await
позволяет преобразовывать асинхронный код в синхронный код (или, по крайней мере, что-то, что выглядит синхронно). Однако этот трюк работает только «изнутри»: внешний интерфейс все еще асинхронный, вы можете просто написать более нормально выглядящий код внутри.
Например:
// await is only available inside async functions, so let's define one:
(async function () {
// magic happens here:
let data = await jq.run(filter, jsonPath);
fs.appendFile('./jqTest.txt', data + "\r\n", (err) => {
if (err) throw err;
console.log("complete!")
});
})(); // ... and invoke it immediately
Внутренне, JavaScript переписывает
x = await f();
doStuffWith(x);
...
в нечто, похожее на
return f().then((x) => {
doStuffWith(x);
...
});
т.е. await
позволяет вытащить содержимое функции обратного вызова в прямой код. Однако в конечном итоге вся функция async
все еще возвращает обещание.