Skip to content

Commit 87452b5

Browse files
committed
feat: Add Modern JavaScript Patterns for Client Scripts
- Add async GlideAjax patterns with promise-based implementations - Add ES6 field management techniques using modern syntax - Add promise-based operations for better asynchronous handling - Include comprehensive documentation and usage examples These patterns demonstrate modern JavaScript techniques in ServiceNow: - Async/await patterns for GlideAjax calls - ES6+ syntax for cleaner, more maintainable code - Promise-based operations for better error handling - Modern client-side development practices
1 parent 5804e23 commit 87452b5

File tree

4 files changed

+2388
-0
lines changed

4 files changed

+2388
-0
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# Modern JavaScript Patterns for ServiceNow Client Scripts
2+
3+
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.
4+
5+
## 📋 Table of Contents
6+
7+
- [Async/Await API Integration](#asyncawait-api-integration)
8+
- [Promise-Based Form Operations](#promise-based-form-operations)
9+
- [ES6+ Form Field Management](#es6-form-field-management)
10+
- [Modern Event Handling](#modern-event-handling)
11+
- [Advanced State Management](#advanced-state-management)
12+
13+
## 🚀 Modern JavaScript Features for ServiceNow
14+
15+
### Async/Await for GlideAjax
16+
Replace callback-heavy GlideAjax patterns with modern async/await syntax for cleaner, more readable code.
17+
18+
### Promise-Based Operations
19+
Implement Promise patterns for form operations, field updates, and user interactions.
20+
21+
### ES6+ Syntax Enhancements
22+
- Template literals for dynamic string building
23+
- Destructuring for clean data extraction
24+
- Arrow functions for concise callback handling
25+
- Classes for reusable form components
26+
27+
### Modern Event Handling
28+
- Event delegation patterns
29+
- Debounced input handling
30+
- Custom event systems
31+
32+
## 🎯 Pattern Categories
33+
34+
### API Integration Patterns
35+
- **Async GlideAjax**: Modern promise-based server communication
36+
- **Fetch-Style Operations**: Consistent API interaction patterns
37+
- **Error Handling**: Comprehensive error management with try/catch
38+
39+
### Form Interaction Patterns
40+
- **Reactive Fields**: Field dependencies with modern observers
41+
- **State Management**: Form state tracking and management
42+
- **Validation**: Real-time validation with debouncing
43+
44+
### User Experience Patterns
45+
- **Progressive Enhancement**: Graceful degradation strategies
46+
- **Loading States**: User feedback during async operations
47+
- **Responsive Design**: Mobile-friendly form interactions
48+
49+
### Performance Patterns
50+
- **Debouncing**: Optimize frequent operations
51+
- **Memoization**: Cache expensive calculations
52+
- **Lazy Loading**: Load data and components on demand
53+
54+
## 🔧 Implementation Guidelines
55+
56+
### Modern JavaScript in ServiceNow
57+
- Use ES6+ features available in modern browsers
58+
- Implement fallbacks for legacy browser support
59+
- Leverage ServiceNow's client-side APIs effectively
60+
61+
### Performance Best Practices
62+
- Minimize DOM manipulations
63+
- Use efficient event handling patterns
64+
- Implement proper cleanup for memory management
65+
66+
### Code Organization
67+
- Modular function design
68+
- Reusable component patterns
69+
- Clear separation of concerns
70+
71+
## 📊 Pattern Examples
72+
73+
### Before (Traditional)
74+
```javascript
75+
function onChange(control, oldValue, newValue, isLoading) {
76+
if (isLoading || newValue == '') {
77+
return;
78+
}
79+
80+
var ga = new GlideAjax('MyScriptInclude');
81+
ga.addParam('sysparm_name', 'getData');
82+
ga.addParam('sysparm_value', newValue);
83+
ga.getXML(function(response) {
84+
var answer = response.responseXML.documentElement.getAttribute("answer");
85+
if (answer) {
86+
var data = JSON.parse(answer);
87+
g_form.setValue('field1', data.value1);
88+
g_form.setValue('field2', data.value2);
89+
}
90+
});
91+
}
92+
```
93+
94+
### After (Modern)
95+
```javascript
96+
async function onChange(control, oldValue, newValue, isLoading) {
97+
if (isLoading || !newValue) return;
98+
99+
try {
100+
const data = await fetchData(newValue);
101+
updateFormFields(data);
102+
} catch (error) {
103+
handleError(error);
104+
}
105+
}
106+
107+
const fetchData = (value) => {
108+
return new Promise((resolve, reject) => {
109+
const ga = new GlideAjax('MyScriptInclude');
110+
ga.addParam('sysparm_name', 'getData');
111+
ga.addParam('sysparm_value', value);
112+
ga.getXML(response => {
113+
try {
114+
const answer = response.responseXML.documentElement.getAttribute("answer");
115+
resolve(JSON.parse(answer));
116+
} catch (error) {
117+
reject(error);
118+
}
119+
});
120+
});
121+
};
122+
123+
const updateFormFields = ({ value1, value2 }) => {
124+
g_form.setValue('field1', value1);
125+
g_form.setValue('field2', value2);
126+
};
127+
```
128+
129+
## 🛡️ Error Handling Patterns
130+
131+
Modern error handling with comprehensive logging and user feedback:
132+
133+
```javascript
134+
const withErrorHandling = (fn) => {
135+
return async (...args) => {
136+
try {
137+
return await fn(...args);
138+
} catch (error) {
139+
console.error('Operation failed:', error);
140+
g_form.addErrorMessage('An error occurred. Please try again.');
141+
throw error;
142+
}
143+
};
144+
};
145+
```
146+
147+
## 🔄 State Management Patterns
148+
149+
Implement reactive state management for complex form interactions:
150+
151+
```javascript
152+
class FormStateManager {
153+
constructor() {
154+
this.state = new Proxy({}, {
155+
set: this.handleStateChange.bind(this)
156+
});
157+
}
158+
159+
handleStateChange(target, property, value) {
160+
target[property] = value;
161+
this.notifySubscribers(property, value);
162+
return true;
163+
}
164+
}
165+
```
166+
167+
## 📈 Performance Optimization
168+
169+
### Debouncing Pattern
170+
```javascript
171+
const debounce = (func, delay) => {
172+
let timeoutId;
173+
return (...args) => {
174+
clearTimeout(timeoutId);
175+
timeoutId = setTimeout(() => func.apply(this, args), delay);
176+
};
177+
};
178+
```
179+
180+
### Memoization Pattern
181+
```javascript
182+
const memoize = (fn) => {
183+
const cache = new Map();
184+
return (...args) => {
185+
const key = JSON.stringify(args);
186+
if (cache.has(key)) {
187+
return cache.get(key);
188+
}
189+
const result = fn(...args);
190+
cache.set(key, result);
191+
return result;
192+
};
193+
};
194+
```
195+
196+
## 🔗 Related Documentation
197+
198+
- [ServiceNow Client Scripts Documentation](https://developer.servicenow.com/dev.do#!/learn/learning-plans/tokyo/new_to_servicenow/app_store_learnv2_automatingapps_tokyo_client_scripts)
199+
- [Modern JavaScript (ES6+) Guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide)
200+
- [ServiceNow GlideForm API](https://developer.servicenow.com/dev.do#!/reference/api/tokyo/client/c_GlideFormAPI)

0 commit comments

Comments
 (0)