I'm using node-gcloud https://github.com/GoogleCloudPlatform/gcloud-node to interact with Google Cloud Storage.
I'm developing a node.js server (my first node.js project) to provide a small set of APIs to clients. Basically when an user uploads a file the API call return the signed url to show that file.
The getSignedUrl function is asynchronous https://googlecloudplatform.github.io/gcloud-node/#/docs/v0.8.1/storage?method=getSignedUrl and I can't find a way to return that result from another function.
I've started playing with Bluebird promises but I can't get to the point of it. Here is my code:
var _signedUrl = function(bucket,url,options) {
new Promise(function (resolve, reject) {
var signed_url
bucket.getSignedUrl(options, function(err, url) {
signed_url = err || url;
console.log("This is defined: " + signed_url)
return signed_url
})
})
}
var _getSignedUrl = function(url) {
new Promise(function(resolve) {
var options = config.gs
, expires = Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14)
, bucket = project.storage.bucket({bucketName: config.gs.bucket, credentials: config.gs })
, signed_url = null
options.action = 'read'
options.expires = expires// 2 weeks.
options.resource= url
signed_url = resolve(_signedUrl(bucket,url,options))
console.log("This is undefined: " + signed_url)
return JSON.stringify( {url: signed_url, expires: expires} );
});
}
I think that I'm missing the basics of how it is supposed to work, so any hint will be appreciated.
Edit:
I have reworked my solution as for the first comment:
getSignedUrl: function() {
var options = config.gs
, expires = Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14)
, bucket = project.storage.bucket({bucketName: config.gs.bucket, credentials: config.gs })
, signed_url = null
options.action = 'read'
options.expires = expires// 2 weeks.
options.resource= this.url
Promise.promisifyAll(bucket);
return bucket.getSignedUrlAsync(options).catch(function(err) {
return url; // ignore errors and use the url instead
}).then(function(signed_url) {
return JSON.stringify( {url: signed_url, expires: expires} );
});
}
It's not clear to me how the double return is supposed to work, but if I keep the return bucket
what I get is this output:
{ url: { _bitField: 0, _fulfillmentHandler0: undefined, _rejectionHandler0: undefined, _promise0: undefined, _receiver0: undefined, _settledValue: undefined, _boundTo: undefined } }
, and if remove it and keep the
return JSON.stringify( {url: signed_url, expires: expires} );
I get undefined as before. What am I missing?
Some points:
new Promise(function(res, rej){ … })
resolver callback, you actually need to call resolve()
or reject()
(asynchronously), not return
anything.resolve
doesn't return anything. You seemed to use it like a "wait" operation that returns the result of the promise, but such is impossible. A promise is still asynchronous.new Promise
at all. Use Promisification instead.Your code should rather look like
var gcloud = require('gcloud');
Promise.promisifyAll(gcloud); // if that doesn't work, call it once on a
// specific bucket instead
function getSignedUrl(url) {
var options = config.gs,
expires = Math.round(Date.now() / 1000) + (60 * 60 * 24 * 14),
bucket = project.storage.bucket({bucketName: config.gs.bucket, credentials: config.gs });
options.action = 'read';
options.expires = expires; // 2 weeks.
options.resource = url;
return bucket.getSignedUrlAsync(options).catch(function(err) {
return url; // ignore errors and use the url instead
}).then(function(signed_url) {
console.log("This is now defined: " + signed_url);
return JSON.stringify( {url: signed_url, expires: expires} );
});
}