Await socket Response
You have a few flags (removed, responded) which are almost equivalent and possibly useless. removeListener() won't cause any error if listener has been already removed then removed is unnecessary. After you called removeListener() your callback won't be called then also responded (which BTW is a misleading name) is unnecessary. Also, setTimeout() won't call its callback twice then again responded isn't necessary.

Use const instead of let whenever possible and declare your variables (usually one per line) when you initialize them. In (untested) code:

if (!socket) {
    reject("Socket supplied is not valid.");
    return;
}

if (socket.disconnected) {
    reject("Socket is disconnected");
    return;
}

const timeout = setTimeout(() =&gt; {
   socket.removeListener(wait_key, callback);

   if (error_on_timeout) {
       reject("Socket timeout");
   } else {
       resolve(null);
   }
}, max_wait)

const callback = (data) =&gt; {
    clearTimeout(timeout);
    socket.removeListener(wait_key, callback);
    resolve(data);
};

socket.on(wait_key, callback);
socket.emit(emit, data)


Few more notes: resolve() and reject() won't stop execution then you need to add the proper return. Use semicolon consistently: someone prefers to avoid semicolon as much as possible, pick a style and use it consistently.