javascript - AngularJS Asynchronous calls with multiple databases and a save not in the correct order -
javascript - AngularJS Asynchronous calls with multiple databases and a save not in the correct order -
i quite confused @ whole javascript , asynchronous calls.
it simple function really, or thought. have function searches 2 different databases site id. if site id cannot found in db1, has search db2 , save site in db1.
pass in siteid search siteid in db1 cannot find siteid in db1, search db2 get site db2 save site in db1 search db1 site again return site display uimy code below:
var xsite=''; function getsite(siteid) { xsite = siteid; var predicate = predicate.create('siteid', '==', siteid); homecoming entityquery.from(entitynames.site) //db1 .where(predicate) .using(manager).execute() .then(querysucceeded, _queryfailed); function querysucceeded(data) { if (data.results.length == 0) { logerror('site not found!'); //staticdb separate datacontext staticdb.getstaticsites(xsiteid).then(function(data) { addsitetoorg(data[0], 8); save().then(function() { common.$timeout(function() { homecoming entityquery.from(entitynames.site) .where(predicate) .using(manager).execute() .then(querysucceeded2, _queryfailed); }, 1250); }); }); } else { activesite = data.results[0]; if (activesite.devices.length == 0) { getsystemsatsite(activesite); } homecoming activesite; } function querysucceeded2(data) { activesite = data.results[0]; //this value right if (activesite.devices.length == 0) { getsystemsatsite(activesite); } homecoming activesite; } } function addsitetoorg(site, org) { var newsite = manager.createentity('site', { siteid: site.siteid, sitename: site.name, country: site.country }); } function save() { homecoming manager.savechanges() .then(savesucceeded, savefailed); function savesucceeded(result) { logsuccess('saved data', result, true); } function savefailed(error) { var msg = config.apperrorprefix + 'save failed: ' + breeze.saveerrormessageservice.geterrormessage(error); error.message = msg; logerror(msg, error); throw error; } }
what happens out of chaos: (numbers same above)
pass in siteid search siteid in db1 cannot find siteid in db1, search db2 -> timeout-> 7. homecoming site display ui get site db2 search db1 site again save site in db1after save done, i'm not sure goes, because did not go chained function.
i'm not sure how save site before have go find , homecoming ui. have tried using q, defer, timeout, something... anything! can't seem in right order of action.
why going out of order? shouldn't ".then()" execute after save?
edit 1: homecoming querysucceed2 goes no where. function returned undefined before ever executes addsitetoorg() or save().
this such fun question had seek ... or close.
i wrote mocha/chai test hits breeze doccode sample web api has 2 controllers happen access same database (northwind).
i made 2 simplifying assumptions:
that siteid
key property "site" type (just customerid
key "customer" type).
the metadata same entities in question (here "customer", "site") in both info sources. i'm imagining db2 has same construction db1.
here test wrote:
it("your example", function(done){ var id = alfredsid; // testfns.wellknowndata.emptyguid; var ds1 = new breeze.dataservice({servicename: 'http://localhost:58066/breeze/northwind'}); var ds2 = new breeze.dataservice({servicename: 'http://localhost:58066/breeze/northwinddto'}); em.fetchentitybykey('customer', id, true /* search cache first; go server */) .then(firstquerysuccess) .then(confirmresult) .then(done, done); // test artifact; ignore in code function firstquerysuccess(data){ var entity = data.entity; if (entity){ homecoming entity; } // got // not found; query 1 time again in sec info source switchtodatasource2(em); var key = data.entitykey; // same key before var promise = em.fetchentitybykey(key, false /* go server #2*/) .then(secondquerysuccess); switchtodatasource1(em); // immediately, before async phone call returns homecoming promise; // sec query } function secondquerysuccess(data){ var entity = data.entity; if (!entity){ homecoming entity; } // can't find in 2nd source either; give // although retrieved ds2, it's new in ds1 entity.entityaspect.setadded(); homecoming em.savechanges([entity]) .then(function savesucceeded (){ homecoming entity; }, // we've got it; no need refetch it. function savefailed (error) { if (/duplicate/.test(error.message)) { // it's in ds1; race condition?; assume , reverse add together entity.entityaspect.setunchanged(); homecoming entity; } else { // bad happened; remove cache , forwards error entity.entityaspect.setdetached(); homecoming breeze.q.reject(error); } }); } function switchtodatasource1(em){ em.setproperties({dataservice: ds1}); } function switchtodatasource2(em){ em.setproperties({dataservice: ds2}); em.metadatastore.adddataservice(ds2, true /*overwrite if found */); } // add together own success function want entity // here apply chai.js expectations confirm entity expected. function confirmresult(entity){ if (entity){ var key = entity.entityaspect.getkey(); expect(entity.entitytype.shortname).to.equal('customer', 'entitytype '+entity.entitytype.name); expect(entity.entityaspect.entitystate).to.equal(breeze.entitystate.unchanged, 'entitystate '+entity.entityaspect.entitystate.name); expect(key.values[0]).to.equal(id, 'key '+json.stringify(key)); } else { expect(false).to.equal(true, 'did not find entity id='+id+ ' in either info source'); } } })
observations this "works" in sense the code want do ... hope you want do. seem me follow intended sequence described.
i'm hampered fact don't have 2 databases. 2 info sources in illustration refer same physical database. don't have case client in ds2 not ds1. means entity id seek either found in ds1 or not found in either of them
i can simulate inability find in ds1 commenting out quick homecoming in firstquerysuccess
// if (entity){ homecoming entity; } // got
notice sec query, have alter manager's dataservice
momentarily ds2 (switchtodatasource2
). long plenty breeze evaluate query , fire @ server. switch ds1 (in switchtodatasource1
) subsequent queries em using ds1. need ds2 length of time takes issue query server.
notice ensure in switchtodatasource2
metadatastore
in em
associated both ds1 , ds2. i'm leveraging simplifying assumption #2 mentioned above.
now entity is found in sec info source.
i have set it's state "added". that's critical! retrieved entity ds2 in unchanged state. doesn't exist in ds1 have alter state "added".
now can save ds1.
i not have re-fetch entity after save. have in cache. can homecoming when/if save succeeds.
the final .then(done, done)
testing artifact , would not part of code. code whatever appropriate within confirmresult
.
in practice, save fails for me because entity exists in ds1 (remember, ds1 , ds2 map same database). won't issue you.
or maybe happen too! it's possible user looks same siteid
@ same time , happens save ds1 before do. you'll have lost race , you'll same "duplicate" error get. show how might handle in savefailed
callback.
one final point: notice every promise phone call returns either promise or value. must maintain callbacks flowing. otherwise, chain broken , app seems drift space.
only final confirmresult
callback neglects homecoming value; , shouldn't homecoming value or else mocha test falls apart (don't create me explain). confirmresult
throw exception if entity fails expectation ... , that's fine.
enjoy!
javascript angularjs breeze
Comments
Post a Comment