javascript - Väntar på ett löfte som jag skapade avslutar koden utan fel
Jag verifierade i konsolen att coordinator.setupPromise är ett Promise, men när jag kör await coordinator.setupPromise så når koden aldrig utskriftsstatements efter await och istället för att vänta avslutas den bara omedelbart. Exempel på konsoloutput:
tsx main.ts
setup
await setup Promise { <pending> }
Här är min kod:
import { ChildProcessWithoutNullStreams, spawn } from "child_process";
import { getPortFree, sleep } from "../utils";
import 'child_process'
import fetch, { RequestInit } from "node-fetch";
import { SocksProxyAgent } from "socks-proxy-agent";
class TorInstance {
socksPort: number;
controlPort: number;
dataDir: string = `./datadirs/${Math.random().toString(36).slice(2)}`;
torProcess: ChildProcessWithoutNullStreams;
agent;
setupRes;
setupPromise = new Promise(res => { this.setupRes = res });
constructor(socksPort?, controlPort?) {
this.setup();
}
private async setup(socksPort?, controlPort?) {
let port1 = await getPortFree();
let port2 = await getPortFree();
this.socksPort = socksPort ?? port1.port
this.controlPort = controlPort ?? port2.port
port1.server.close();
port2.server.close();
// tor --SocksPort 11111 --ControlPort 11112 --DataDirectory test1
this.torProcess = spawn(`tor`, ['--SocksPort', this.socksPort, '--ControlPort', this.controlPort, '--DataDirectory', this.dataDir].map(String));
this.torProcess.stdout.setEncoding('utf8');
this.torProcess.stdout.on('data', (data) => {
if (data.toString().includes(`[notice] Bootstrapped 100% (done): Done`)) { this.setupRes() }
})
this.agent = new SocksProxyAgent(`socks5h://127.0.0.1:${this.socksPort}`);
}
public fetch(url: string, options?: RequestInit) {
return fetch(url, {
...options,
agent: this.agent
})
}
public dispose() {
this.torProcess.kill();
}
}
class TorCoordinator {
instances: TorInstance[] = [];
currentIndex = 0;
setupRes;
setupPromise = new Promise(res => { this.setupRes = res; })
constructor(num: number) {
this.createInstances(num);
}
fetch(url: string, options?: RequestInit) {
return this.instances[this.currentIndex++].fetch(url, options);
}
createInstances(num) {
let newInstances: TorInstance[] = [];
for (let i = 0; i < num; i++) {
let newInstance = new TorInstance();
newInstances.push(newInstance);
newInstance.setupPromise.then(() => {
console.log('setup!!')
this.instances.push(newInstance)
this.setupRes();
})
// todo monitor console output for [notice] Bootstrapped 100% (done): Done, and only add to main list then
}
}
}
async function test() {
console.log('setup')
let coordinator = new TorCoordinator(10);
console.log('await setup',coordinator.setupPromise)
await coordinator.setupPromise;
console.log('done await')
coordinator.fetch('https://api.ipify.org?format=json').then(res => res.text().then(console.log))
coordinator.fetch('https://api.ipify.org?format=json').then(res => res.text().then(console.log))
await sleep(10000)
}
test();
Och utils.ts är:
import { SocksProxyAgent } from "socks-proxy-agent"
export function sleep(m) { return new Promise(r => setTimeout(r, m)) }
export const torAgent = new SocksProxyAgent('socks5h://127.0.0.1:9050');
import { Readable } from 'stream';
export async function streamToBuffer(stream) {
const chunks = [];
for await (const chunk of stream) {
chunks.push(chunk); // Collect each Uint8Array chunk
}
// Concatenate all chunks into a single Buffer
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
const buffer = Buffer.alloc(totalLength);
let position = 0;
for (const chunk of chunks) {
buffer.set(chunk, position);
position += chunk.length;
}
return buffer;
}
export async function streamToString(stream: ReadableStream) {
const reader = stream.getReader()
let html = ''
while (true) {
const { value, done } = await reader.read()
if (value) {
html += new TextDecoder().decode(value)
}
if (done) {
return html
}
}
}
export async function streamToStringOld(stream: ReadableStream<Uint8Array<ArrayBufferLike>>) {
const chunks: any = [];
// Use async iteration to read from the stream
for await (const chunk of stream) {
chunks.push(chunk); // Collect each Uint8Array chunk
}
// Concatenate all chunks into a single Uint8Array
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
const resultArray = new Uint8Array(totalLength);
let position = 0;
for (const chunk of chunks) {
resultArray.set(chunk, position);
position += chunk.length;
}
// Convert the Uint8Array to a string
return new TextDecoder().decode(resultArray);
}
import net from "net"
export async function getPortFree():Promise<{port:number,server:net.Server}> {
return new Promise( res => {
const srv = net.createServer();
srv.listen(0, () => {
// @ts-ignore
const port = srv.address().port
res({port,server:srv});
});
})
}
Jag försökte vänta på ett löfte som jag hade skapat tidigare, men istället för att vänta på att passera till nästa rad, avslutas koden bara utan att något fel uppstår.
Svar #1
Din huvudfil väntar inte på test()-funktionen. Så när du kallar test() kan den bara avsluta när den är klar med att kalla på den funktionen.
Du borde prova detta istället
(async () => {
await test();
})().catch(console.error);
