roswell: шустрее try-catch будет, если не такой синтетический пример брать, а реальную ситуацию, особенно если функция будет использоваться многократно
return await - избыточная конструкция, достаточно return
чтоб зарежектить результат async function достаточно throw
так же если не перехватить reject из await - это равносильно throw
throw внутри таймаута сработает на другом потоке исполнения (другой итерации event-loop) и следовательно вывалится в общий трэйс, try-catch его не перехватит
bernex: async function еще до исполнения своего кода возвращает Promise, а сам код исполняется по nextTick, аналогично Promise.resolve().then(function() { /* как тут */ });
Для .map .forEach и lodash этого будет достаточно, чтоб запустить следующую итерацию, следовательно асинхронный код будет выполнятся параллельно (точнее, при первой возможности)
Umid: можно, но сложно и зачастую не нужно. В принципе, все что есть на npm так или иначе написано на ванильном апи, но почему бы не пользоваться тем, что уже сделали другие?