问题
I'm new to AngularJS and Breeze. I'm trying to save changes and have a problem with that. Here's my code:
In controller:
function update() {
vm.loading = true;
return datacontext.saveSettings().then(function () {
vm.loading = false; // never gets called
}).fail(function (data) {
vm.loading = false; // never gets called
});
}
In datacontext:
function saveSettings() {
if (manager.hasChanges()) {
manager.saveChanges() // breaks here if there are changes
.then(saveSucceeded)
.fail(saveFailed)
.catch(saveFailed);
} else {
log("Nothing to save");
return false;
};
}
The error is thrown in angular.js
and it's very unhelpful TypeError: undefined is not a function
I guess there is something simple I'm missing here, but can't figure out what is it.
Want to note that it does send correct data to SaveChanges method on server, but the error is thrown before any response from the server received. After the response is received it throws another error TypeError: Cannot read property 'map' of undefined
but it might be related to the fact the response I return is invalid. I haven't got to that part yet.
Can anyone anyone help with it? I'm lost here.
UPDATE
Here is how I construct my dataservice and manager:
var serviceName = "http://admin.localhost:33333/api/breeze/"; //
var ds = new breeze.DataService({
serviceName: serviceName,
hasServerMetadata: false,
useJsonp: true,
jsonResultsAdapter: jsonResultsAdapter
});
var manager = new breeze.EntityManager({ dataService: ds });
model.initialize(manager.metadataStore);
回答1:
Two problems:
Your
datacontext
method does not return a promise so the caller cannot find anything to hang thethen
orfail
call on.You should be calling
catch
, notfail
1. Return a promise
Your saveSettings
method did not return a result in the success case so it must fail. Your method must also return a promise in the fail case ... or it will also fail.
And while I'm here, since there is no real difference between your success and fail case, you might as well move the vm.loading
toggle to the finally
clause.
Try this instead:
function update() {
vm.loading = true;
return datacontext.saveSettings()
.then(function () {
// .. success handling if you have any
})
.catch(function (data) {
// .. fail handling if you have any
})
.finally(funtion() {
vm.loading = false; // turn it off regardless
});
}
And now the dataContext
... notice the two return
statements return a promise.
function saveSettings() {
if (manager.hasChanges()) {
return manager.saveChanges()
.then(saveSucceeded)
.catch(saveFailed);
} else {
log("Nothing to save");
// WHY ARE YOU FAILING WHEN THERE IS NOTHING TO SAVE?
// Breeze will handle this gracefully without your help
return breeze.Q.reject(new Error('Nothing to save'));
};
}
2. Use catch
I assume you have configured Breeze to use Angular's $q
for promises (you should be using the "breeze.angular" service and have injected "breeze" somewhere).
$q does not have a fail method! The equivalent is catch
. For some reason you have both attached to your query. You'll get the ReferenceError
exception immediately, before the server has a chance to respond ... although it will launch the request and you will get a callback from the server too.
Try just:
return manager.saveChanges()
.then(saveSucceeded)
.catch(saveFailed);
You see many Breeze examples that call fail
and fin
. These are "Q.js" methods; "Q.js" is an alternative promise library - one used by Breeze/KnockOut apps and it was the basis for Angular's $q
.
Both "Q.js" and $q
support the now-standard catch
and finally
promise methods. We're slowly migrating our example code to this standard. There is a lot of old fail
/finally
code around in different venues. It will take time.
Sorry for the confusion.
回答2:
Update savesetting
function like below to return Promise
.
function saveSettings() {
if (manager.hasChanges()) {
return manager.saveChanges(); // return promise
} else {
log("Nothing to save");
return false;
};
}
Then you can call then and fail in update function like following.
function update() {
vm.loading = true;
return datacontext.saveSettings().then(function () {
vm.loading = false; // never gets called
}).fail(function (data) {
vm.loading = false; // never gets called
});
}
来源:https://stackoverflow.com/questions/28500013/angularjs-throws-exception-when-trying-to-savechanges-with-breeze