In my case I have one repository like this from temphire (breeze)
define(['durandal/system'], function (system) {
var Repository = (function () {
var repository = function (entityManagerProvider, entityTypeName, resourceName, fetchStrategy) {
.........
this.find = function (predicate) {
var query = breeze.EntityQuery
.from(resourceName)
.where(predicate);
return executeQuery(query);
};
function executeQuery(query) {
return entityManagerProvider.manager()
.executeQuery(query.using(fetchStrategy || breeze.FetchStrategy.FromServer))
.then(function (data) { return data.results; });
}
................
};
return repository;
})();
return {
create: create,
getCtor: Repository
};
function create(entityManagerProvider, entityTypeName, resourceName, fetchStrategy) {
return new Repository(entityManagerProvider, entityTypeName, resourceName, fetchStrategy);
}
});
NOW
HOW CAN DO LIKE SOME THIS
repository.query(predicate).execute();
function query(predicate) {
return query = breeze.EntityQuery
.from(resourceName)
.where(predicate);
};
function executeQuery(query) {
return entityManagerProvider.manager().executeQuery(query.using(fetchStrategy || breeze.FetchStrategy.FromServer)).then(function(data) {
return data.results;
});
}
function execute() -- >
return executeQuery
the first action return query and after to execute
many thanks
I think the problem with what you are trying is that return terminates execution. If you want to do something as well as return in that function, then you need to do it before you return.
If, on the other hand, you really need to return the value and then execute something, then you should have the method that calls the function expecting the return, call the function to get the return value, and then have that calling function execute the thing you want executed. If that execution needs some data from the function that returns the value, then return that information with the value returned, and pass it into the function that does the execution.
Use
executeQueryLocally // This is syn
instead of
executeQuery // This is async
executeQuery sync
Related
I'm desperately trying to recover the value of a callback function but I have no idea how to do that. I have a function where I execute this code:
if (final.error !== undefined) {
console.log("Initial authentication:", final.error_description, "Please refresh the authentication grant");
extAuthCallback(84);
} else {
tokens.set('access_token', final.access_token)
.set('expires_in', final.expires_in)
.set('refresh_token', final.refresh_token)
.set('refresh_date', moment())
.write()
extAuthCallback(1);
}
});
Who performs this function:
function extAuthCallback(result) {
return result;
}
And which is called by this variable:
let authentication = auth.extAuth(access_token, auth.extAuthCallback);
I would like my `authentication' variable to take the value returned in the callback, and I have no idea how to do that. Returning the callback function to my original function doesn't work.
You could use a promise, would need to use an async function as well though.
function asyncExtAuth(access_token) {
return new Promise(resolve => {
auth.extAuth(access_token, resolve);
});
}
let authentication = await asyncExtAuth(access_token);
I am trying to return data of 3 async api calls using promise.all()
function apiReq1(apiCred){
const rds = new apiCred.RDS();
var request = rds.describeDBInstances();
return request.promise();
}
function getAPIs (apiCred) {
return Promise.all([apiReq1(apiCred), apiReq2(apiCred), apiReq3(apiCred)]).then(function(data) {
console.log(data[0])
console.log(data[1])
console.log(data[2])
return data
// ideal return
//myMap.set('bar', data[0])
//.set('foo', data[1])
//.set('baz', data[2]);
//return myMap
});
}
// Function that is calling getAPIs
function getAll() {
apiCred = getApiCred()
page = getAPIs(apiCred)
console.log(page)
}
The console.log prints out the data as expected however I would like to be able to return the data object or ideally a new object with all three iterables to whatever calls getAPIs(). This is the first time I am trying to use promises and I feel there is a key async concept I am missing here on trying to return the data.
You can just do:
function getAPIs (apiCred) {
return Promise.all([apiReq1(apiCred), apiReq2(apiCred), apiReq3(apiCred)]).then(function(data) {
return {
'bar': data[0],
'foo': data[1],
'baz': data[2]
}
});
}
However, this function still returns a promise, so you cant access the result in the caller synchronously.
You need to modify your getAll method as follows
function getAll() {
apiCred = getApiCred()
return getAPIs(apiCred).then(page => {
console.log(page);
//DO YOUR THING
})
}
I'm aware that there are similar questions, but I haven't seen any that address this chaining pattern.
I have the following:
var runTests = function (chain, resolutionTest) {
return chain.then(function (result) {
if (result)
return result; // Early return if the previous tests were successful. This is where I want to prevent other attempts.
const attempt = tryOpenStream(resolutionTest).then(streamToDom);
return attempt;
});
}
// from someplace else
numTests = resolutionTests.length;
return resolutionTests.reduce(runTests, Promise.resolve()); // start reduce with an empty promise
The problem that I'm encountering is that I'm calling tryOpenStream many times even after I've captured a result.
Options I'm considering:
Raise some global flag that just prevents further execution from within the chain. Yuck, because the chain still proceeds, it's just emptied.
throw new Error(result) instead of return result. This would break the chain (I think...) but it's misusing Error and would be easily misunderstood by another developer.
How can I break this chain at return result;?
UPDATE 1
I'm trying the following:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(function (result) {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTestBuilder.buildTests().then(function (resolutionTests) {
numTests = resolutionTests.length;
return resolutionTests.reduceRight(makeTest, function () { Promise.reject("No resolutions succeeded.") })();
});
However no calls to runTest are invoked. This is a bit of new syntax for me so I'll research some and update with any findings.
UPDATE 2
I was missing the () to invoke the reduceRight. Though now I'm seeing that reject called even with success... though when I step through, that rejection isn't invoked. It's as if by the time I get a result back, all links in the chain have been invoked.
Both flags and exceptions can be used, but as you noticed they're not the proper tool.
Instead, use recursion, like in #IsiahMeadows' answer, or a right fold:
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest(result) {
if (result)
return result;
return tryOpenStream(resolutionTest).then(streamToDom).then(runMoreTests);
};
}
return Promise.resolve(resolutionTests.reduceRight(makeTest, x => x)(undefined));
or better written as
var makeTest = function (runMoreTests, resolutionTest) {
return function runTest() {
return tryOpenStream(resolutionTest).then(streamToDom).then(result => {
if (result)
return result;
else
return runMoreTests();
});
};
}
return resolutionTests.reduceRight(makeTest, () => Promise.reject("nothing succeeded"))();
Try using this:
function runTests(resolutionTest) {
return tryOpenStream(resolutionTest).then(streamToDom)
}
// from someplace else
function loop(tests, i) {
if (i === tests.length) return undefined
return runTests(tests[i]).then(function (result) {
if (result) return result
return loop(tests, i + 1)
})
}
return loop(resolutionTests, 0)
Although I do wonder why you can't use an exception to denote your tryOpenStream failed. That would actually simplify your code some.
I am writing a recursive function inside for loop like below:
var output = [];
function myFunc(myValue, callback) {
myAnotherFunc(myValue, function(result){
for (var i=0; i < result.myKey.length; i++){
if(result.myKey[i].name === 'something'){
myFunc(result.myKey[i].recurseValue, function(recursiveResult){
//some recursive stuff
output.push(recursiveResult.someValue)
});
}
}
});
}
And initiating the recursive function like below:
myFunc(initialValue, function(result){
//some stuff
});
Its working fine, but how do I know when my recursive flow ends so that I can do something else from the final output?
You can use Promises™! It's basically a way to defer a callback till after an Asynchronous flow is completed: Example:
// Instead of passing your normal callback, we'll tell the
// function to use resolve(results) to pass your results to the
// next code block so it can do something after all your recursions are completed
const someTask = new Promise(resolve => myFunc(initialValue, resolve))
someTask.then(result => {
/* Do Something with the results at the end of aformentioned callback hell :D */
})
PS. You also have to modify your original function signature to:
function myFunc(myValue, callback) {
myAnotherFunc(myValue, function(result){
const cbks = [] //Store the async resuls of all myFunc() executions
for (i=0; i < result.myKey.length; i++){
if(results[i] === 'something'){
cbks.push(new Promise(res => myFunc(result[i].recurseValue, res)))
}
}
//Run all async myFunc() and return the results in an array
Promise.all(cbks).then(callback)
});
}
function myFunc(resolve) {
var rec = function(myVal, cb) {
myOther(recurseValue, function(result) {
var hasName = result[myKey].filter(function(obj) {
return obj.name === 'something';
})[0];
if (hasName) {
rec(hasName[recurseValue], function(recResult) {
// other recursive stuff
});
} else {
resolve(?); // whatever the final value should be
}
});
};
return rec;
}
function recurseAsync(f, initial) {
return new Promise(function(resolve, reject) {
f(resolve)(initial);
});
}
Couple notes.
The recurseAsync function takes a function that takes a resolution callback and returns a recursive function that calls that callback when finished to resolve the promise. myFunc has been altered to fit that format.
I used array filtering rather than a for loop and shortened some names. Also if you are using a variable for object access use [] instead of .. To use the final value when all of this is finished you can call .then on the promise.
// whatever initial value 'foo' should be
var finished = recurseAsync(myFunc, foo);
finished.then(function(finalValue) {
// do something with the final result of all the recursion
});
I've created a function into backbone view that return true or false under some condition.
The issue is that the return value is evere undefined. I think it is a scope problem.
This issue is different from Ajax return because my return is inside an iteration and not in an ajx call. The previous Ajax call in my code is sync and not async.The console.log inside my iteration is correctly printed, only return statement seems doesn't work.
isAlreadyRegistered: function(){
this.checkUser = new Utenti();
this.checkUser.fetch({async:false});
_.each(this.checkUser.models, function (user) {
if(user.get("idTwitter") === this.utente.get('idTwitter')){
console.log("gia reg");
return true;
} else {
console.log("non reg");
return false;
}
}, this);
}
console.log(isAlreadyRegistered());//ever undefined
You don't want to use each, but every or some. They will return booleans depending on what your callback invocations did return.
isAlreadyRegistered: function(){
this.checkUser = new Utenti();
this.checkUser.fetch({async:false});
var id = this.utente.get('idTwitter');
return _.some(this.checkUser.models, function (user) {
return user.get("idTwitter") === id;
});
}