Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# 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

- [Async/Await API Integration](#asyncawait-api-integration)
- [Promise-Based Form Operations](#promise-based-form-operations)
- [ES6+ Form Field Management](#es6-form-field-management)
- [Modern Event Handling](#modern-event-handling)
- [Advanced State Management](#advanced-state-management)

## 🚀 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)
```javascript
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)
```javascript
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:

```javascript
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:

```javascript
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
```javascript
const debounce = (func, delay) => {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
};
```

### Memoization Pattern
```javascript
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

- [ServiceNow Client Scripts Documentation](https://developer.servicenow.com/dev.do#!/learn/learning-plans/tokyo/new_to_servicenow/app_store_learnv2_automatingapps_tokyo_client_scripts)
- [Modern JavaScript (ES6+) Guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide)
- [ServiceNow GlideForm API](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/client/c_GlideFormAPI)
Loading
Loading