Во-первых, я должен упомянуть, что я уже просматриваю много вопросов в stackoverflow, но многие не отвечают на мой вопрос. Не говоря уже о том, что многие даже не имеют ответа.
Как мне добиться следующего, убедившись, что functionB()
выполняется после завершения functionA()
?
Примечание. Я не хочу преобразовывать свои асинхронные функции в new Promise(resolve=>{...})
потому что мне также придется преобразовать someServiceThatMakesHTTPCall()
и любые другие асинхронные функции в стеке вызовов, что является большим изменением.
function functionThatCannotHaveAsyncKeyword() {
functionA()
.then(async function() {
await functionB();
})
.then(function() {
console.info('last');
});
}
async function functionA() {
console.info('first');
await someServiceThatMakesHTTPCall();
}
async function functionB() {
console.info('second');
await someServiceThatMakesHTTPCall();
}
🤔 А знаете ли вы, что...
JavaScript имеет множество библиотек и фреймворков, таких как jQuery, Angular, и Vue.js.
Ваш подход с использованием await
в обратном вызове async
then
будет работать, но он излишне сложен, если все, который вы хотите сделать, это вызвать функцию async
и распространить ее результат по цепочке. Но если вы занимаетесь другими делами и хотите использовать преимущества синтаксиса функций async
, это нормально. Я вернусь к этому через минуту.
async
функции возвращают промисы, поэтому вы просто возвращаете результат вызова вашей функции:
function functionThatCannotHaveAsyncKeyword() {
functionA()
.then(function() {
return functionB(someArgument);
})
.then(function() {
console.info('last');
}); // <=== Note: You need a `catch` here, or this function needs
// to return the promise chain to its caller so its caller can
// handle errors
}
Если вы хотите передать значение разрешения functionA
в functionB
, вы можете сделать это еще более прямо:
functionA()
.then(functionB)
// ...
Когда вы возвращаете промис из обратного вызова then
, промис, созданный вызовом then
, является решил промисом, который вы возвращаете: он будет ждать, пока этот другой промис будет выполнен, а затем согласуется таким же образом.
Пример:
const wait = (duration, ...args) => new Promise(resolve => {
setTimeout(resolve, duration, ...args);
});
async function functionA() {
await wait(500);
return 42;
}
async function functionB() {
await wait(200);
return "answer";
}
functionB()
.then(result => {
console.info(result); // "answer"
return functionA();
})
.then(result => {
console.info(result); // 42
})
.catch(error => {
// ...handle error...
});
Возвращаясь к вашему подходу с использованием обратного вызова async
then
: это тоже работает и имеет смысл, когда вы делаете больше вещей:
const wait = (duration, ...args) => new Promise(resolve => {
setTimeout(resolve, duration, ...args);
});
async function functionA() {
await wait(500);
return 42;
}
async function functionB() {
await wait(200);
return "answer";
}
functionB()
.then(async (result) => {
console.info(result); // "answer"
const v = await functionA();
if (v < 60) {
console.info("Waiting 400ms...");
await wait(400);
console.info("Done waiting");
}
console.info(v); // 42
})
.catch(error => {
// ...handle error...
});
если someServiceThatMakesHTTPCall
является асинхронным, вы можете избежать всего этого, выполнив следующие действия:
function functionThatCannotHaveAsyncKeyword() {
functionA()
.then(function() {
return functionB()
})
.then(function() {
console.info('last');
});
}
function functionA() {
console.info('first');
return someServiceThatMakesHTTPCall();
}
function functionB() {
console.info('second');
return someServiceThatMakesHTTPCall();
}
Вы можете использовать обещание внутри первого метода как
function functionThatCannotHaveAsyncKeyword() {
return new Promise(async(resolve, reject)=> {
await functionA();
await functionB();
console.info('last');
resolve();
});
}
async function functionA() {
console.info('first');
await someServiceThatMakesHTTPCall();
}
async function functionB() {
console.info('second');
await someServiceThatMakesHTTPCall();
}