Можно ли объявлять асинхронными функции, которые возвращают Promise
Например возьмем модуль request (его callback, не promise версию) и напишем такой код:
const request = require('request');
async function google(){
return new Promise((resolve, reject) => {
request('http://www.google.com', function (error, response, body) {
if(error) reject(error);
resolve(body);
});
});
}
Данная функция объявлена как async что значит она возвращает Promise в любом случае, в ней мы делаем return другого Promise, сути это в принципе не меняет, но встает несколько вопросов:
- Стоит ли так делать?
- Это говнокод?
- Почему стоит или не стоит так делать?
- Как это влияет на прожорливость и скорость?
Ответы (1 шт):
Меня довольно давно интересоавл этот вопрос и я пытался найти ответы в официальной документации но либо я плохо ищу либо там нет такой информации. Если кто в курсе, поделитесь пожалуйста ссылкой в комментарии.
Тем не менее я нашел способ проверить эффективность данного подхода и как оказалось использование ключевого слова async и явное создание Promise объекта посредством выражения new Promise(...) внутри функции является не эффективным и вот почему.
На основе примера "Почему использовать return await плохая идея" я создал тестовый файл и проверил выполнение кода таким образом:
// promise-hooks.js
const hooks = require("async_hooks");
const fs = require("fs");
let indent = 0;
module.exports = hooks.createHook({
promiseResolve(asyncId) {
const indentStr = " ".repeat(indent);
fs.writeSync(1, `${indentStr}resolved: ${asyncId}\n`);
},
init(asyncId, type, triggerAsyncId, resource) {
const eid = hooks.executionAsyncId();
const indentStr = " ".repeat(indent);
const dt1 = `${indentStr}${type}(${asyncId})`;
const dt2 = `trigger: ${triggerAsyncId}`;
const dt3 = `resource: ${resource.parentId}`;
const dt4 = `execution: ${eid}`;
fs.writeSync(1, `${dt1}, ${dt2}, ${dt3}, ${dt4}\n`);
},
before(asyncId) {
const indentStr = " ".repeat(indent);
fs.writeSync(1, `${indentStr}before: ${asyncId}\n`);
indent += 2;
},
after(asyncId) {
indent -= 2;
const indentStr = " ".repeat(indent);
fs.writeSync(1, `${indentStr}after: ${asyncId}\n`);
},
destroy(asyncId) {
const indentStr = " ".repeat(indent);
fs.writeSync(1, `${indentStr}destroy: ${asyncId}\n`);
},
});
Тестовый код (без использования async)
const hooks = require("./promise-hooks.js");
hooks.enable();
function asyncTest() {
return new Promise((resolve, reject) => resolve());
}
asyncTest();
Результат выполнения:
PROMISE(2), trigger: 1, resource: undefined, execution: 1
resolved: 2
Теперь обявляем асинхронную функцию с помощью async
const hooks = require("./promise-hooks.js");
hooks.enable();
async function asyncTest() {
return new Promise((resolve, reject) => resolve());
}
asyncTest();
Результат выполнения:
PROMISE(2), trigger: 1, resource: undefined, execution: 1
PROMISE(3), trigger: 1, resource: undefined, execution: 1
resolved: 3
resolved: 2
before: 2
PROMISE(4), trigger: 3, resource: undefined, execution: 2
after: 2
before: 4
resolved: 2
resolved: 4
after: 4
Как видим из примера в результате получаем два Promise-объекта, похоже ключевое слово async неявно оборачивает возвращаемый результат функции в Promise, что по сути является неэффективным. Поэтому в случае явного использования new Promise(), ключевое слово async лучше не использовать и наоборот.