Skip to content

Latest commit

 

History

History
200 lines (164 loc) · 5.91 KB

File metadata and controls

200 lines (164 loc) · 5.91 KB

Modern JavaScript Patterns for ServiceNow Client Scripts

This collection demonstrates modern JavaScript ES6+ patterns and best practices specifically adapted for ServiceNow client scripts, providing clean, maintainable, and performance-optimized code for form interactions.

📋 Table of Contents

🚀 Modern JavaScript Features for ServiceNow

Async/Await for GlideAjax

Replace callback-heavy GlideAjax patterns with modern async/await syntax for cleaner, more readable code.

Promise-Based Operations

Implement Promise patterns for form operations, field updates, and user interactions.

ES6+ Syntax Enhancements

  • Template literals for dynamic string building
  • Destructuring for clean data extraction
  • Arrow functions for concise callback handling
  • Classes for reusable form components

Modern Event Handling

  • Event delegation patterns
  • Debounced input handling
  • Custom event systems

🎯 Pattern Categories

API Integration Patterns

  • Async GlideAjax: Modern promise-based server communication
  • Fetch-Style Operations: Consistent API interaction patterns
  • Error Handling: Comprehensive error management with try/catch

Form Interaction Patterns

  • Reactive Fields: Field dependencies with modern observers
  • State Management: Form state tracking and management
  • Validation: Real-time validation with debouncing

User Experience Patterns

  • Progressive Enhancement: Graceful degradation strategies
  • Loading States: User feedback during async operations
  • Responsive Design: Mobile-friendly form interactions

Performance Patterns

  • Debouncing: Optimize frequent operations
  • Memoization: Cache expensive calculations
  • Lazy Loading: Load data and components on demand

🔧 Implementation Guidelines

Modern JavaScript in ServiceNow

  • Use ES6+ features available in modern browsers
  • Implement fallbacks for legacy browser support
  • Leverage ServiceNow's client-side APIs effectively

Performance Best Practices

  • Minimize DOM manipulations
  • Use efficient event handling patterns
  • Implement proper cleanup for memory management

Code Organization

  • Modular function design
  • Reusable component patterns
  • Clear separation of concerns

📊 Pattern Examples

Before (Traditional)

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') {
        return;
    }
    
    var ga = new GlideAjax('MyScriptInclude');
    ga.addParam('sysparm_name', 'getData');
    ga.addParam('sysparm_value', newValue);
    ga.getXML(function(response) {
        var answer = response.responseXML.documentElement.getAttribute("answer");
        if (answer) {
            var data = JSON.parse(answer);
            g_form.setValue('field1', data.value1);
            g_form.setValue('field2', data.value2);
        }
    });
}

After (Modern)

async function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || !newValue) return;
    
    try {
        const data = await fetchData(newValue);
        updateFormFields(data);
    } catch (error) {
        handleError(error);
    }
}

const fetchData = (value) => {
    return new Promise((resolve, reject) => {
        const ga = new GlideAjax('MyScriptInclude');
        ga.addParam('sysparm_name', 'getData');
        ga.addParam('sysparm_value', value);
        ga.getXML(response => {
            try {
                const answer = response.responseXML.documentElement.getAttribute("answer");
                resolve(JSON.parse(answer));
            } catch (error) {
                reject(error);
            }
        });
    });
};

const updateFormFields = ({ value1, value2 }) => {
    g_form.setValue('field1', value1);
    g_form.setValue('field2', value2);
};

🛡️ Error Handling Patterns

Modern error handling with comprehensive logging and user feedback:

const withErrorHandling = (fn) => {
    return async (...args) => {
        try {
            return await fn(...args);
        } catch (error) {
            console.error('Operation failed:', error);
            g_form.addErrorMessage('An error occurred. Please try again.');
            throw error;
        }
    };
};

🔄 State Management Patterns

Implement reactive state management for complex form interactions:

class FormStateManager {
    constructor() {
        this.state = new Proxy({}, {
            set: this.handleStateChange.bind(this)
        });
    }
    
    handleStateChange(target, property, value) {
        target[property] = value;
        this.notifySubscribers(property, value);
        return true;
    }
}

📈 Performance Optimization

Debouncing Pattern

const debounce = (func, delay) => {
    let timeoutId;
    return (...args) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => func.apply(this, args), delay);
    };
};

Memoization Pattern

const memoize = (fn) => {
    const cache = new Map();
    return (...args) => {
        const key = JSON.stringify(args);
        if (cache.has(key)) {
            return cache.get(key);
        }
        const result = fn(...args);
        cache.set(key, result);
        return result;
    };
};

🔗 Related Documentation