I have built up a javascript file that starts with:
var myApp = function () { var CLIENT_ID = 'xxxxxxx'; var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"]; var SCOPES = 'https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/analytics.readonly https://www.googleapis.com/auth/drive.readonly'; var authorizeButton = document.getElementById('authorize-button'); return {
The functions are declared like:
getSent: function(callback) { var request = gapi.client.gmail.users.messages.list({ 'userId': 'me', 'labelIds': 'SENT', 'maxResults': 10 }); request.execute(function(response) { $.each(response.messages, function() { var messageRequest = gapi.client.gmail.users.messages.get({ 'userId': 'me', 'id': this.id }); messageRequest.execute(myApp.appendMessageRow); }); }); },
And then run through a single function that calls others:
myApp.init();
How can I defer a function to be run after my google request function getsent() has been fully completed. I have tried using callbacks to another function and it runs but it runs while the getsent() is still being executed. Can I use the jQuery method defered to run the callback when done?
I have tried: myApp.getSent(myApp.gMailSyncComplete()); // Runs early
and I tried: myApp.getSent().done(myApp.gMailSyncComplete()); // no jQuery done defined
4 Answers
Answers 1
Some important errors in your code:
- You are creating a function
getSent
that accepts a callback, but you are not calling the callback at all so it won't get executed ever. You should execute the callback when everything else is done. - You are not waiting for all message requests to be completed. You can use a library like async which has the method map to be able to execute all requests in parallel and wait for all of them to be completed before calling the callback.
With these two things in mind, and using async
, this would be an example of the resulting code:
getSent: function (callback) { var request = gapi.client.gmail.users.messages.list({ 'userId': 'me', 'labelIds': 'SENT', 'maxResults': 10 }) request.execute(function (response) { async.map(response.messages, function (msg, cb) { var messageRequest = gapi.client.gmail.users.messages.get({ 'userId': 'me', 'id': msg.id }) messageRequest.execute(function (result) { myApp.appendMessageRow(result) cb() }) }, function (err) { if (err) throw err callback() }) }) }
- Lastly, when invoking this function, keep in mind that the
callback
parameter must be a function.
To make things clear, let's translate the code you wrote, myApp.getSent(myApp.gMailSyncComplete())
, into an equivalent structure:
var callback = myApp.gMailSyncComplete() myApp.getSent(callback)
When you do this, you are not passing the function but the result of the function, because you are executing it. That's why it gets executed immediately. The correct way to do this would be the following:
var callback = myApp.gMailSyncComplete myApp.getSent(callback)
Or, in your one-liner example, myApp.getSent(myApp.gMailSyncComplete)
Answers 2
you can use javascript promise.
function testPromise() { let p1 = new Promise( // The resolver function is called with the ability to resolve or // reject the promise (resolve, reject) => { /*your async function*/ } ); // defined what to do when the promise is resolved with the then() call, // and what to do when the promise is rejected with the catch() call p1.then( // Log the fulfillment value function(val) { log.insertAdjacentHTML('beforeend', val + ') Promise fulfilled (<small>Async code terminated</small>)<br/>'); }) .catch( // Log the rejection reason (reason) => { console.log('Handle rejected promise ('+reason+') here.'); }); }
Answers 3
You could use jQuery promise()
, check the example below.
getSent: function() { var request = gapi.client.gmail.users.messages.list({ 'userId': 'me', 'labelIds': 'SENT', 'maxResults': 10 }); request.execute(function(response) { $.each(response.messages, function() { var messageRequest = gapi.client.gmail.users.messages.get({ 'userId': 'me', 'id': this.id }); messageRequest.execute(myApp.appendMessageRow); }); }); }, ... $.when( myApp.getSent() ).done(function() { // do whatever you want in here as callback });
Answers 4
Inside of your getSent function create a jQuery Deferred object and return a promise. Then after request.execute has finished you can call resolve/reject. I created a small snippet to show example. Maybe you can modify to fit your needs
$(document).ready(function () { var i =0; function getText() { var deferred = $.Deferred(); setTimeout(function () { i++; deferred.resolve("text " + i); }, 3000); return deferred.promise(); } getText().then(function (value) { console.log(value); }).then(function () { getText().then(function (value2) { console.log(value2); }); }); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
0 comments:
Post a Comment