Doing some client-side JavaScript development, which requires me to call a client-side API which only accepts one parameter at a time (cough, cough, facebook).
Ba开发者_JAVA百科sically i need to call an API method twice:
someFBApi.requestPerms('email')
someFBApi.requestPerms('publish_stream')
Now, i have a wrapper function for this call which looks like this:
function requestPermission(permission, callback) {
someFBApi.requestPerms(permission, callback);
}
But the problem is, i have to call the function "requestPermission" twice from all over the place:
requestPermission('email', function(perm1granted) {
requestPermission('publish_stream', function(perm2granted) {
// do something with perm 1 and perm 2
I would like to be able to do this:
requestPermissions('email,publish_stream', function(firstPerm,secondPerm) {
// do something with firstPerm, secondPerm
I know i have to call FB API twice (fine), but i want that 'doubling up' to occur in that function (not all over the place). Know what i mean?
So, i'll accept an answer of two forms:
- Can i pass an array of strings, iterate through those? (maybe JSON?)
- Delimeted-string, then split the string in the function.
Keep in mind the function returns a value indicating whether or not the permission was granted. So it needs to accept an array/delimited list of strings and return an array/delimited list of strings.
The more simple the solution, the better. (jQuery fine)
Don't be tempted to use the string parsing solution. An array is cleaner and simpler:
/* note: permisions is expected to be an array */
function requestPermission(permissions) {
for (var i=0; i<permissions.length; i++) {
doSomething(permissions[i]);
}
}
Now, the only problem would seem to be what to do with the callback. I'm assuming that the API is asynchronous and you'd want something like this:
doSomething(when_done)->doSomething...(finally)->execute_callback
For that you can use a sort of recursion. Except it wouldn't really be recursion in the traditional sense since each call happen asynchronously. Something like:
/* note: permisions is expected to be an array */
function requestPermission(permissions,callback) {
var p = permissions.shift();
var f = callback;
if (permissions.length > 0) {
// if this is not the last permission then
// call this function again in the callback:
f = function () {
requestPermission(permissions,callback);
}
}
someFBApi.requestPerms(p,f);
}
Now you can use it like this:
requestPermissions(['email','publish_stream'],finalCallback);
Using some array juggling you can drain items from a permissions
array while accruing results in a results
array. Tricky use of requestPerms
's callback parameter will have our function be called once for each permission request to be performed, culminating in a call to the user's callback
function once all of the permission requests have been performed.
function requestPermissions(permissions, callback, results) {
if (typeof(results) == "undefined") {
results = [];
}
// Call requestPerms with the first element in permissions and have
// it add the result to the results array and then call requestPermissions()
// again recursively to handle the next request.
if (permissions.length > 0) {
var permission = permissions.shift();
someFBApi.requestPerms(permission, function(result) {
results.add(result);
requestPermissions(permissions, callback, results);
}
}
// We've handled all of the permission requests, so now--finally--call the
// user's callback function.
else {
callback.call(results);
}
}
# Usage
requestPermissions(
['email', 'publish_stream'],
function(emailPerm, publishPerm) {
// Do something with emailPerm and publishPerm.
}
);
This is completely untested, but hey, that's what you get for free!
.
function requestPermissions(permissions, callback, ret) {
// ret is a map of the success of the permissions
if (!ret) ret = {};
// Request the first permission in the array.
FB.requestPerms(permissions[0], function (r) {
ret[permissions[0]] = r;
// If it was successful and there are more permissions
// to ask for, call requestPermissions again.
// (If it wasn't successful, don't continue.)
if (r && permissions[1])
requestPermissions(permissions.slice(1), callback, ret);
// Otherwise, call the callback.
else
callback(ret);
});
}
requestPermissions(['email', 'publish_stream'], function (success) {
if (success['email'] && success['publish_stream'])
// ...
});
The above solution works sequentially, that is, one after another. I'm not sure how the Facebook API works, but if it allows requesting multiple permissions simultaneously, this could work too:
function requestPermissions(permissions, callback) {
var ret = {};
var count = permissions.length;
// jQuery to make things easier
$.each(permissions, function (i, value) {
FB.requestPerms(permissions, function (success) {
ret[value] = success;
if (--count == 0) // Last one?
callback(ret);
});
});
}
精彩评论