forked from Breeze/breeze.js.labs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbreeze.savequeuing.js
165 lines (149 loc) · 6.18 KB
/
breeze.savequeuing.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//#region Copyright, Version, and Description
/*
* Copyright 2014 IdeaBlade, Inc. All Rights Reserved.
* Use, reproduction, distribution, and modification of this code is subject to the terms and
* conditions of the IdeaBlade Breeze license, available at http://www.breezejs.com/license
*
* Author: Ward Bell
* Version: 1.0.4
* --------------------------------------------------------------------------------
* Adds "Save Queuing" capability to new EntityManagers
* "Save Queuing" automatically queues and defers an EntityManager.saveChanges call
* when another save is in progress for that manager.
*
* Depends on Breeze (which it patches) and Q.js (not for use in Angular ... yet)
*
* Without "Save Queuing", an EntityManager will throw an exception when
* saveChanges is called while another save is in progress.
*
* "Save Queuing" is experimental. It may become part of BreezeJS in future
* although not necessarily in this form or with this API
*
* Must call EntityManager.enableSaveQueuing(true) to turn it on;
* EntityManager.enableSaveQueuing(false) restores the manager's original
* saveChanges method as it was at the time saveQueuing was first enabled.
*
* This module adds "enableSaveQueuing" to the EntityManager prototype.
* Calling "enableSaveQueuing(true)" adds a new _saveQueuing object
* to the manager instance.
*
* !!! Use with caution !!!
* "Save Queuing" is recommended only in simple "auto-save" scenarios wherein
* users make rapid changes and the UI saves immediately as they do so.
* It is usually better (and safer) to disable save in the UI
* while waiting for a prior save to complete
*
* All members of EntityManager._saveQueuing are internal;
* touch them at your own risk.
*/
//#endregion
(function (definition, window) {
if (window.breeze && window.Q) {
definition(window.breeze, window.Q);
} else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
// CommonJS or Node
var b = require('breeze');
var q = require('Q');
definition(b, q);
} else if (typeof define === "function" && define["amd"] && !window.breeze) {
// Requirejs / AMD
define(['breeze', 'Q'], definition);
} else {
throw new Error("Can't find breeze and/or Q");
}
}(function (breeze, Q) {
'use strict';
var EntityManager = breeze.EntityManager;
/**
Enable (default) or disable "Save Queuing" for this manager
**/
EntityManager.prototype.enableSaveQueuing = function (enable) {
enable = enable === undefined ? true : enable;
if (!this._saveQueuing) {
this._saveQueuing = new SaveQueuing(this);
}
if (enable) {
this.saveChanges = saveChangesWithQueuing;
} else {
this.saveChanges = this._saveQueuing.baseSaveChanges;
}
};
var SaveQueuing = function (entityManager) {
this.entityManager = entityManager;
this.baseSaveChanges = entityManager.saveChanges;
this.isSaving = false;
this.saveQueue = [];
};
SaveQueuing.prototype.isEnabled = function () {
return this.entityManager.saveChanges === saveChangesWithQueuing;
};
/**
Replacement for EntityManager.saveChanges, extended with "Save Queuing"
**/
function saveChangesWithQueuing() {
var saveQueuing = this._saveQueuing;
var args = [].slice.call(arguments);
if (saveQueuing.isSaving) {
// save in progress; queue the save for later
return saveQueuing.queueSaveChanges(args);
} else {
// note that save is in progrees; then save
saveQueuing.isSaving = true;
return saveQueuing.innerSaveChanges(args);
}
}
SaveQueuing.prototype.queueSaveChanges = function (args) {
var self = this;
var deferredSave = Q.defer();
self.saveQueue.push(deferredSave);
// clone saveOptions because may change later, before this save is dequeued
args[1] = breeze.core.extend(new breeze.SaveOptions(),
args[1] || this.entityManager.saveOptions || breeze.SaveOptions.defaultInstance);
var savePromise = deferredSave.promise;
return savePromise
.then(function () { return self.innerSaveChanges(args); })
.then(null,function (error) { self.saveFailed(error); });
};
SaveQueuing.prototype.innerSaveChanges = function (args) {
var self = this;
return self.baseSaveChanges.apply(self.entityManager, args)
.then(function (saveResult) { return self.saveSucceeded(saveResult); })
.then(null, function (error) { self.saveFailed(error); });
};
// Default methods and Error class for initializing new saveQueuing objects
SaveQueuing.prototype.saveSucceeded = defaultSaveSucceeded;
SaveQueuing.prototype.saveFailed = defaultSaveFailed;
SaveQueuing.prototype.QueuedSaveFailedError = QueuedSaveFailedError;
function defaultSaveSucceeded(saveResult) {
var saveQueuing = this;
var deferredSave = saveQueuing.saveQueue.shift();
if (deferredSave) {
deferredSave.resolve();
}
if (saveQueuing.saveQueue.length === 0) {
saveQueuing.isSaving = false;
}
return saveResult;
};
function defaultSaveFailed(error) {
var saveQueuing = this;
saveQueuing.isSaving = false;
var saveQueue = saveQueuing.saveQueue;
var deferredSave;
// clear the save queue, calling reject on each deferred save
while (deferredSave = saveQueue.shift()) {
deferredSave.reject(new saveQueuing.QueuedSaveFailedError(error, saveQueuing));
}
throw error; // so rest of current promise chain can hear error
}
//#region QueuedSaveFailedError
//Custom Error sub-class; thrown when rejecting queued saves.
function QueuedSaveFailedError(errObject) {
this.name = "QueuedSaveFailedError";
this.message = "Queued save failed";
this.innerError = errObject;
}
QueuedSaveFailedError.prototype = new Error();
QueuedSaveFailedError.prototype.constructor = QueuedSaveFailedError;
//#endregion
}, this));