Lesson 40-WinterJS Basic Programming

Basic Syntax and APIs

Module Import and Export

ESM Standard Import and Export

// Basic import and export
import { readFile } from 'fs';
import * as fs from 'fs';

export const version = '1.0.0';
export function hello() { /*...*/ }

// Default export
export default class Server { /*...*/ }

// Optimized dynamic import
const module = await import('./dynamic_module.js', {
  assert: { type: 'js' } // Type assertion
});

// Dynamic import with caching
const moduleCache = new Map();

async function getModule(path) {
  if (moduleCache.has(path)) {
    return moduleCache.get(path);
  }
  const module = await import(path);
  moduleCache.set(path, module);
  return module;
}

Performance Comparison Test

// Static import vs dynamic import performance test
console.time('static_import');
import { heavyFunction } from './heavy_module.js';
heavyFunction();
console.timeEnd('static_import');

console.time('dynamic_import');
const { heavyFunction } = await import('./heavy_module.js');
heavyFunction();
console.timeEnd('dynamic_import');

File System Operations

Asynchronous File API

import { promises as fs } from 'fs';

// High-performance file reading and writing
async function processLargeFile() {
  // Stream-based processing for large files
  const readStream = fs.createReadStream('large.txt', { highWaterMark: 1024 * 64 });
  const writeStream = fs.createWriteStream('output.txt');

  for await (const chunk of readStream) {
    const processed = transformChunk(chunk); // Custom processing function
    writeStream.write(processed);
  }
}

// Atomic write operation
async function atomicWrite(path, data) {
  const tempPath = `${path}.tmp`;
  await fs.writeFile(tempPath, data);
  await fs.rename(tempPath, path); // Atomic rename
}

Performance Optimization Techniques

// Batch file operation optimization
async function batchProcessFiles(filePaths) {
  // Process in parallel with limited concurrency
  const concurrency = 4;
  const batches = chunkArray(filePaths, concurrency);

  for (const batch of batches) {
    await Promise.all(batch.map(processSingleFile));
  }
}

function chunkArray(array, size) {
  return Array.from({ length: Math.ceil(array.length / size) }, (_, i) =>
    array.slice(i * size, i * size + size)
  );
}

Network Programming Basics

HTTP Server Implementation

import { serve } from 'http';

const server = serve({ port: 8000 });

console.log('HTTP Server running on http://localhost:8000');

for await (const req of server) {
  // Route handling
  if (req.url === '/' && req.method === 'GET') {
    req.respond({
      headers: { 'Content-Type': 'text/plain' },
      body: 'Hello World\n'
    });
  } else {
    req.respond({ status: 404, body: 'Not Found' });
  }
}

HTTP Client Example

import { connect } from 'http';

async function fetchData(url) {
  const { hostname, port, pathname } = new URL(url);
  const conn = connect({ hostname, port });

  const request = [
    `GET ${pathname} HTTP/1.1`,
    `Host: ${hostname}`,
    'Connection: close',
    '',
    ''
  ].join('\r\n');

  conn.write(request);

  let response = '';
  for await (const chunk of conn) {
    response += chunk;
  }

  conn.close();
  return parseHttpResponse(response);
}

Timers and Event Loop

Lightweight Timers

// High-precision timer
const start = performance.now();
setTimeout(() => {
  const end = performance.now();
  console.log(`Execution time: ${end - start}ms`);
}, 100);

// Using microtask queue
Promise.resolve().then(() => {
  console.log('Microtask executed');
});

// Performance comparison
console.time('setTimeout');
setTimeout(() => console.timeEnd('setTimeout'), 0);
console.time('Promise');
Promise.resolve().then(() => console.timeEnd('Promise'));

Event Loop Optimization

// Task chunk processing
async function processInChunks(items, chunkSize, processItem) {
  for (let i = 0; i < items.length; i += chunkSize) {
    const chunk = items.slice(i, i + chunkSize);
    await Promise.all(chunk.map(processItem));
    // Yield to event loop
    await new Promise(resolve => setTimeout(resolve, 0));
  }
}

Processes and Subprocesses

Lightweight Process Management

import { spawn } from 'process';

// Spawn subprocess
const child = spawn('ls', ['-lh', '/usr']);

// Real-time output handling
child.stdout.on('data', (data) => {
  console.log(`stdout: ${data}`);
});

child.stderr.on('data', (data) => {
  console.error(`stderr: ${data}`);
});

child.on('close', (code) => {
  console.log(`Subprocess exit code: ${code}`);
});

// Inter-process communication
const { fork } = require('process');
const child = fork('worker.js');

child.send({ command: 'start' });
child.on('message', (msg) => {
  console.log('Received message from subprocess:', msg);
});

Using Built-in Toolchain

Package Manager

Basic Operations

# Initialize project
winterpkg init

# Install dependency
winterpkg add lodash@4.17.21

# Install dev dependency
winterpkg add --dev typescript

# Update dependencies
winterpkg update

# Remove dependency
winterpkg remove lodash

Advanced Features

# View dependency tree
winterpkg tree

# Clear cache
winterpkg cache clean

# Offline mode installation
winterpkg install --offline

Testing Framework

Unit Test Example

// test/math.test.js
import { add, multiply } from '../src/math.js';

describe('Math Operations', () => {
  it('should add correctly', () => {
    expect(add(2, 3)).toBe(5);
  });

  it('should multiply correctly', () => {
    expect(multiply(2, 3)).toBe(6);
  });
});

Test Commands

# Run tests
winter test

# Run tests with coverage
winter test --coverage

# Run specific tests
winter test --grep="add"

Bundling Tool

Configuration Example

// winter.config.js
export default {
  bundle: {
    target: 'esm',
    minify: true,
    sourcemap: true,
    splitChunks: {
      chunks: 'all',
      minSize: 10240 // 10KB
    }
  }
};

Bundling Commands

# Bundle for development
winter bundle --dev

# Bundle for production
winter bundle --prod

# Analyze bundle size
winter bundle --analyze

Script Executor

Common Commands

# Run script
winter run app.js

# Run with environment variables
winter run --env=production server.js

# Debug mode
winter run --inspect-brk app.js

Custom Scripts

// package.winter
{
  "scripts": {
    "dev": "winter run --watch src/server.js",
    "build": "winter bundle --prod",
    "test": "winter test"
  }
}

REPL Usage

Interactive Environment

# Start REPL
winter repl

# Use module in REPL
> import { add } from 'math'
> add(2, 3)
5

# View help
> .help
Available commands:
  .exit    Exit REPL
  .help    Show help
  .clear   Clear context

Advanced Usage

// Execute file in REPL
> .load src/utils.js

// Set variable
> const PI = 3.14159

// View command history
> .history

synchronous Programming

Promise and async/await

Basic Usage

// Promise chain
fetchData()
  .then(processData)
  .then(saveData)
  .catch(handleError);

// async/await syntax
async function main() {
  try {
    const data = await fetchData();
    const processed = await processData(data);
    await saveData(processed);
  } catch (err) {
    handleError(err);
  }
}

Parallel Execution

// Fetch multiple resources in parallel
async function fetchAll() {
  const [user, posts] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/posts')
  ]);

  return {
    user: await user.json(),
    posts: await posts.json()
  };
}

Event-Driven Programming

Custom EventEmitter

class EventEmitter {
  constructor() {
    this.listeners = {};
  }

  on(event, listener) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(listener);
  }

  emit(event, ...args) {
    if (this.listeners[event]) {
      for (const listener of this.listeners[event]) {
        listener(...args);
      }
    }
  }
}

// Usage example
const emitter = new EventEmitter();
emitter.on('data', (data) => {
  console.log('Received data:', data);
});
emitter.emit('data', { message: 'Hello' });

Event Stream Processing

// Writable stream example
class WritableStream {
  constructor() {
    this.listeners = { data: [], end: [] };
  }

  write(data) {
    for (const listener of this.listeners.data) {
      listener(data);
    }
  }

  end() {
    for (const listener of this.listeners.end) {
      listener();
    }
  }
}

Asynchronous I/O Operations

File Operation Example

import { promises as fs } from 'fs';

async function processFile() {
  try {
    const content = await fs.readFile('input.txt', 'utf8');
    const processed = content.toUpperCase();
    await fs.writeFile('output.txt', processed);
  } catch (err) {
    console.error('File processing failed:', err);
  }
}

Network Request Example

import { connect } from 'http';

async function httpGet(url) {
  const { hostname, port, pathname } = new URL(url);
  const conn = connect({ hostname, port });

  const request = [
    `GET ${pathname} HTTP/1.1`,
    `Host: ${hostname}`,
    'Connection: close',
    '',
    ''
  ].join('\r\n');

  conn.write(request);

  let response = '';
  for await (const chunk of conn) {
    response += chunk;
  }

  conn.close();
  return parseResponse(response);
}

Concurrency Control

Promise Concurrency Limit

async function runWithConcurrency(tasks, concurrency) {
  const results = [];
  const executing = new Set();

  for (const task of tasks) {
    const p = task().then(res => {
      executing.delete(p);
      return res;
    });

    executing.add(p);
    results.push(p);

    if (executing.size >= concurrency) {
      await Promise.race(executing);
    }
  }

  return Promise.all(results);
}

// Usage example
const tasks = Array(10).fill(() => fetch('https://api.example.com/data'));
runWithConcurrency(tasks, 3);

Task Queue Implementation

class TaskQueue {
  constructor(concurrency) {
    this.concurrency = concurrency;
    this.running = 0;
    this.queue = [];
  }

  pushTask(task) {
    this.queue.push(task);
    this.next();
  }

  next() {
    while (this.running < this.concurrency && this.queue.length) {
      const task = this.queue.shift();
      task().finally(() => {
        this.running--;
        this.next();
      });
      this.running++;
    }
  }
}

// Usage example
const queue = new TaskQueue(3);
for (let i = 0; i < 10; i++) {
  queue.pushTask(() => fetch(`https://api.example.com/data/${i}`));
}

Asynchronous Exception Handling

Error Handling Patterns

// Promise error handling
fetchData()
  .then(data => processData(data))
  .catch(err => {
    if (err instanceof NetworkError) {
      retryFetch();
    } else {
      console.error('Unknown error:', err);
    }
  });

// async/await error handling
async function main() {
  try {
    const data = await fetchData();
    await processData(data);
  } catch (err) {
    if (err instanceof NetworkError) {
      await retryFetch();
    } else {
      console.error('Processing failed:', err);
    }
  }
}

Global Error Capture

// Unhandled Promise rejection
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Promise Rejection:', reason);
});

// Uncaught exception
process.on('uncaughtException', (err) => {
  console.error('Uncaught Exception:', err);
  process.exit(1); // Recommended to exit process
});

Error Boundary Pattern

async function withErrorBoundary(fn, fallback) {
  try {
    return await fn();
  } catch (err) {
    console.error('Error boundary caught:', err);
    return fallback;
  }
}

// Usage example
const result = await withErrorBoundary(
  () => fetchData(),
  { default: 'data' }
);
Share your love