#typescript #async-await
#typescript #асинхронный-ожидание #async-ожидание
Вопрос:
Добрый день, гуру,
я структурировал свой код, чтобы разрешить динамический ввод строки (sCmd) от пользователя, затем строка будет вставлена в функцию, например
let res = Function("moment", '"use strict";' sCmd).call(this, moment);
вот пример пользовательского ввода, который позволил им вызвать команду ‘await’
let sCmd = `
// ---- cmd START
function simulateFirebaseGet() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved from simulateFirebaseGet()');
}, 2000);
});
}
async function callAsyncFunc() {
console.log('#2 - run callAsyncFunc()');
let res = await simulateFirebaseGet();
console.log('#3 - start wait 2 sec')
console.log('#4 -', res);
console.log('#5 - waited 2 sec')
}
console.log('#1 - START Function()');
callAsyncFunc()
console.log('#6 - STOP Function()');
// ---- cmd END
`;
Но это не работает в соответствии с моими ожиданиями. Журнал консоли
#1 - START Function()
#2 - run callAsyncFunc()
#6 - STOP Function()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
Я ожидаю чего-то ниже
#1 - START Function()
#2 - run callAsyncFunc()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()
Я также предоставил ссылку на StackBlitz. Если я помещу «await» в
await callAsyncFunc()
я получу сообщение об ошибке Error: Unexpected identifier
обновления: после ответа @CertainPerformance я выбрал второй подход, и он выполняется последовательно. круто! Но вскоре я заметил, как только я меняю вызывающего на
console.log("START OUTSIDE Function()");
let res = Function("moment", '"use strict";' sCmd).call(
this,
moment
);
console.log("STOP OUTSIDE Function()");
Вывод журнала консоли как
START OUTSIDE Function()
#1 - START Function()
run helper
#2 - run callAsyncFunc()
STOP OUTSIDE Function()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()
И мне нужно, чтобы она запускалась как
START OUTSIDE Function()
#1 - START Function()
run helper
#2 - run callAsyncFunc()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()
STOP OUTSIDE Function()
В моем случае использования мне пришлось бы выполнять цикл «Function(…).call()», и они должны обрабатываться последовательно. Результаты в более раннем цикле будут использоваться для вычисления в более позднем элементе «Function(…).call()».
Ответ №1:
Либо поместите #6
внутри a .then
после callAsyncFn()
разрешения, либо поместите всю функцию в IIFE, чтобы вы могли await
вызвать callAsyncFn
:
let sCmd = `
// ---- cmd START
function simulateFirebaseGet() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved from simulateFirebaseGet()');
}, 2000);
});
}
async function callAsyncFunc() {
console.log('#2 - run callAsyncFunc()');
let res = await simulateFirebaseGet();
console.log('#3 - start wait 2 sec')
console.log('#4 -', res);
console.log('#5 - waited 2 sec')
}
console.log('#1 - START Function()');
callAsyncFunc().then(() => {
console.log('#6 - STOP Function()');
// ---- cmd END
});
`;
let res = Function("moment", '"use strict";' sCmd).call(this, {});
или
let sCmd = `
// ---- cmd START
(async () => {
function simulateFirebaseGet() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved from simulateFirebaseGet()');
}, 2000);
});
}
async function callAsyncFunc() {
console.log('#2 - run callAsyncFunc()');
let res = await simulateFirebaseGet();
console.log('#3 - start wait 2 sec')
console.log('#4 -', res);
console.log('#5 - waited 2 sec')
}
console.log('#1 - START Function()');
await callAsyncFunc()
console.log('#6 - STOP Function()');
// ---- cmd END
})();
`;
let res = Function("moment", '"use strict";' sCmd).call(this, {});
Вам нужно будет сделать то же самое снаружи — либо await
вызвать сконструированную функцию, либо вызвать .then
ее.
let sCmd = `
// ---- cmd START
function simulateFirebaseGet() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved from simulateFirebaseGet()');
}, 2000);
});
}
async function callAsyncFunc() {
console.log('#2 - run callAsyncFunc()');
let res = await simulateFirebaseGet();
console.log('#3 - start wait 2 sec')
console.log('#4 -', res);
console.log('#5 - waited 2 sec')
}
console.log('#1 - START Function()');
return callAsyncFunc().then(() => {
console.log('#6 - STOP Function()');
// ---- cmd END
});
`;
console.log("START OUTSIDE Function()");
Function("moment", '"use strict";' sCmd).call(
this,
{}
)
.then((res) => {
console.log("STOP OUTSIDE Function()");
});
Комментарии:
1. ваш второй метод сработал! но в моем случае мне нужно выполнить цикл «Function ().call», он не «ждет» снаружи «Function ().call». я обновлю свою логику в своей теме, чтобы разработать более подробную информацию.
2. См. Редактирование, вам нужно сделать то же самое, что вы делали внутри, снаружи тоже, чтобы обещания были правильно соединены вместе
3. ваш код работает. Но для моего варианта использования мне нужно выполнить Function(…).call в форме цикла. это означает, что я не мог управлять числовой функцией (…).call для каждого экземпляра. Ваш цепной метод не подойдет для моего варианта использования: (