0
# Property and Method Access
1
2
Methods for accessing properties and calling methods on promised values, enabling object-oriented programming patterns with promises.
3
4
## Capabilities
5
6
### Property Access
7
8
Methods for accessing properties from promised objects.
9
10
```javascript { .api }
11
/**
12
* Gets property from fulfilled value
13
* @param name - Property name to access
14
* @returns Promise for the property value
15
*/
16
promise.get(name);
17
18
/**
19
* Gets property keys from fulfilled object value
20
* @returns Promise for array of property keys
21
*/
22
promise.keys();
23
```
24
25
**Usage Examples:**
26
27
```javascript
28
const Q = require("q");
29
30
// Basic property access
31
const userPromise = Q.resolve({
32
name: "Alice",
33
email: "alice@example.com",
34
age: 30,
35
preferences: { theme: "dark", language: "en" }
36
});
37
38
userPromise.get("name")
39
.then(name => console.log("User name:", name)); // "Alice"
40
41
userPromise.get("email")
42
.then(email => sendWelcomeEmail(email));
43
44
// Nested property access (requires chaining)
45
userPromise.get("preferences")
46
.then(preferences => preferences.theme)
47
.then(theme => console.log("User theme:", theme)); // "dark"
48
49
// Get all property keys
50
userPromise.keys()
51
.then(keys => console.log("User properties:", keys));
52
// ["name", "email", "age", "preferences"]
53
54
// Conditional property access
55
function getProperty(objectPromise, propertyName, defaultValue) {
56
return objectPromise.get(propertyName)
57
.catch(() => defaultValue);
58
}
59
60
getProperty(userPromise, "nickname", "Unknown")
61
.then(nickname => console.log("Nickname:", nickname));
62
63
// Dynamic property access
64
function extractUserInfo(userPromise, fields) {
65
const extractions = fields.map(field =>
66
userPromise.get(field).catch(() => null)
67
);
68
69
return Q.all(extractions).then(values => {
70
const result = {};
71
fields.forEach((field, index) => {
72
result[field] = values[index];
73
});
74
return result;
75
});
76
}
77
78
extractUserInfo(userPromise, ["name", "email", "phone", "address"])
79
.then(info => console.log("Extracted info:", info));
80
```
81
82
### Method Invocation
83
84
Methods for calling functions and methods on promised values.
85
86
```javascript { .api }
87
/**
88
* Calls method on fulfilled value with arguments
89
* @param name - Method name to call
90
* @param ...args - Arguments to pass to the method
91
* @returns Promise for the method result
92
*/
93
promise.invoke(name, ...args);
94
95
/**
96
* Calls fulfilled value as function with apply semantics
97
* @param thisp - Context object (this value)
98
* @param args - Array of arguments
99
* @returns Promise for the function result
100
*/
101
promise.apply(thisp, args);
102
103
/**
104
* Calls fulfilled value as function with call semantics
105
* @param thisp - Context object (this value)
106
* @param ...args - Arguments to pass to function
107
* @returns Promise for the function result
108
*/
109
promise.call(thisp, ...args);
110
111
/**
112
* Returns bound function for future calls
113
* @param thisp - Context object (this value)
114
* @param ...args - Arguments to pre-bind
115
* @returns Promise for bound function
116
*/
117
promise.bind(thisp, ...args);
118
```
119
120
**Usage Examples:**
121
122
```javascript
123
const Q = require("q");
124
125
// Method invocation on objects
126
const stringPromise = Q.resolve("hello world");
127
128
stringPromise.invoke("toUpperCase")
129
.then(result => console.log(result)); // "HELLO WORLD"
130
131
stringPromise.invoke("substring", 0, 5)
132
.then(result => console.log(result)); // "hello"
133
134
stringPromise.invoke("split", " ")
135
.then(words => console.log("Words:", words)); // ["hello", "world"]
136
137
// Method invocation on complex objects
138
const arrayPromise = Q.resolve([1, 2, 3, 4, 5]);
139
140
arrayPromise.invoke("map", x => x * 2)
141
.then(doubled => console.log("Doubled:", doubled)); // [2, 4, 6, 8, 10]
142
143
arrayPromise.invoke("filter", x => x > 3)
144
.then(filtered => console.log("Filtered:", filtered)); // [4, 5]
145
146
arrayPromise.invoke("reduce", (acc, val) => acc + val, 0)
147
.then(sum => console.log("Sum:", sum)); // 15
148
149
// Function application patterns
150
const calculatorPromise = Q.resolve({
151
add: function(a, b) { return this.precision ? Math.round(a + b) : a + b; },
152
precision: true
153
});
154
155
// Using apply
156
calculatorPromise.get("add")
157
.apply(calculatorPromise, [3.7, 4.3])
158
.then(result => console.log("Applied result:", result));
159
160
// Using call
161
calculatorPromise.get("add")
162
.call(calculatorPromise, 3.7, 4.3)
163
.then(result => console.log("Called result:", result));
164
165
// Function binding
166
const mathFunctionPromise = Q.resolve(Math.pow);
167
168
mathFunctionPromise.bind(null, 2) // Bind first argument to 2
169
.then(powerOfTwo => {
170
return Q.all([
171
powerOfTwo(3), // 2^3 = 8
172
powerOfTwo(4), // 2^4 = 16
173
powerOfTwo(5) // 2^5 = 32
174
]);
175
})
176
.then(results => console.log("Powers of 2:", results));
177
178
// Complex method chaining
179
const userServicePromise = fetchUserService();
180
181
userServicePromise
182
.invoke("authenticate", "user123", "password")
183
.then(authenticated => {
184
if (authenticated) {
185
return userServicePromise.invoke("getUserProfile", "user123");
186
} else {
187
throw new Error("Authentication failed");
188
}
189
})
190
.then(profile => {
191
console.log("User profile:", profile);
192
return userServicePromise.invoke("updateLastLogin", profile.id);
193
})
194
.catch(error => console.error("User service error:", error));
195
```
196
197
### Advanced Property Patterns
198
199
Advanced patterns for working with object properties in promise chains.
200
201
```javascript
202
const Q = require("q");
203
204
// Property extraction utility
205
function extractProperties(objectPromise, propertyPaths) {
206
const extractions = propertyPaths.map(path => {
207
const keys = path.split(".");
208
let current = objectPromise;
209
210
keys.forEach(key => {
211
current = current.get(key);
212
});
213
214
return current.catch(() => undefined);
215
});
216
217
return Q.all(extractions).then(values => {
218
const result = {};
219
propertyPaths.forEach((path, index) => {
220
result[path] = values[index];
221
});
222
return result;
223
});
224
}
225
226
// Usage
227
const complexObjectPromise = Q.resolve({
228
user: {
229
profile: {
230
name: "John",
231
contact: {
232
email: "john@example.com",
233
phone: "555-0123"
234
}
235
},
236
settings: {
237
theme: "dark",
238
notifications: true
239
}
240
}
241
});
242
243
extractProperties(complexObjectPromise, [
244
"user.profile.name",
245
"user.profile.contact.email",
246
"user.settings.theme"
247
]).then(extracted => console.log("Extracted:", extracted));
248
249
// Method chaining helper
250
function chainMethods(objectPromise, methodCalls) {
251
return methodCalls.reduce((promise, { method, args = [] }) => {
252
return promise.invoke(method, ...args);
253
}, objectPromise);
254
}
255
256
// Usage
257
const stringBuilderPromise = Q.resolve("hello");
258
259
chainMethods(stringBuilderPromise, [
260
{ method: "toUpperCase" },
261
{ method: "split", args: [""] },
262
{ method: "reverse" },
263
{ method: "join", args: [""] }
264
]).then(result => console.log("Processed string:", result)); // "OLLEH"
265
266
// Property validation
267
function validateObjectShape(objectPromise, requiredProperties) {
268
return objectPromise.keys().then(availableKeys => {
269
const missing = requiredProperties.filter(prop =>
270
!availableKeys.includes(prop)
271
);
272
273
if (missing.length > 0) {
274
throw new Error(`Missing required properties: ${missing.join(", ")}`);
275
}
276
277
return objectPromise;
278
});
279
}
280
281
// Usage
282
const configPromise = loadConfiguration();
283
284
validateObjectShape(configPromise, ["host", "port", "database"])
285
.then(config => {
286
console.log("Configuration is valid");
287
return initializeWithConfig(config);
288
})
289
.catch(error => console.error("Configuration error:", error));
290
```
291
292
### Object Transformation Patterns
293
294
Patterns for transforming objects through property access and method calls.
295
296
```javascript
297
const Q = require("q");
298
299
// Object mapping utility
300
function mapObjectProperties(objectPromise, mappings) {
301
const promises = Object.keys(mappings).map(newKey => {
302
const mapping = mappings[newKey];
303
304
if (typeof mapping === "string") {
305
// Simple property rename
306
return objectPromise.get(mapping).then(value => ({ [newKey]: value }));
307
} else if (typeof mapping === "function") {
308
// Transform with function
309
return objectPromise.then(obj => ({ [newKey]: mapping(obj) }));
310
} else if (mapping.property && mapping.transform) {
311
// Property with transformation
312
return objectPromise.get(mapping.property)
313
.then(mapping.transform)
314
.then(value => ({ [newKey]: value }));
315
}
316
});
317
318
return Q.all(promises).then(mappedObjects => {
319
return Object.assign({}, ...mappedObjects);
320
});
321
}
322
323
// Usage
324
const rawUserPromise = Q.resolve({
325
firstName: "John",
326
lastName: "Doe",
327
emailAddress: "john.doe@example.com",
328
birthDate: "1990-01-15"
329
});
330
331
mapObjectProperties(rawUserPromise, {
332
fullName: obj => `${obj.firstName} ${obj.lastName}`,
333
email: "emailAddress",
334
age: {
335
property: "birthDate",
336
transform: birthDate => {
337
const birth = new Date(birthDate);
338
const today = new Date();
339
return today.getFullYear() - birth.getFullYear();
340
}
341
}
342
}).then(transformedUser => {
343
console.log("Transformed user:", transformedUser);
344
// { fullName: "John Doe", email: "john.doe@example.com", age: 34 }
345
});
346
```