-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async to promises. writeGltf, writeBinaryGltf, writeFile -- callbacks to Promises #135
Conversation
expect(gltf.buffers.CesiumTexturedBoxTest.uri).toEqual('CesiumTexturedBoxTest.bin'); | ||
readFile(outputBufferPath) | ||
.then(function(outputData) { | ||
expect(bufferEqual(outputData, bufferData)).toBe(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fairly certain I shouldn't have to be nesting .then
like this, but I am unsure how I could write this in order to have outputData
accessible by the second .then
function
I have attempted the code below, but that results in outputData
being undefined.
writeGltf(gltf, options)
.then(function() {
expect(gltf.buffers.CesiumTexturedBoxTest.extras).not.toBeDefined();
expect(gltf.buffers.CesiumTexturedBoxTest.uri).toEqual('CesiumTexturedBoxTest.bin');
})
.then(function() {
readFile(outputBufferPath);
})
.then(function(outputData) {
expect(bufferEqual(outputData, bufferData)).toBe(true);
done();
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoshuaStorm
You need to return a promise to do chaining like that.
writeGltf(gltf, options)
.then(function() {
expect(gltf.buffers.CesiumTexturedBoxTest.extras).not.toBeDefined();
expect(gltf.buffers.CesiumTexturedBoxTest.uri).toEqual('CesiumTexturedBoxTest.bin');
return readFile(outputBufferPath);
})
.then(function(outputData) {
expect(bufferEqual(outputData, bufferData)).toBe(true);
done();
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lasalvavida
I appreciate the quick responses to these questions. That makes a lot of sense but I seemed to have just been gleaning over this fact while reading the documentation.
}) | ||
.catch(function(err) { | ||
done(); | ||
throw err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The three above tests are failing
The spy is never being triggered and I am not exactly sure why. I do a similar spy setup for writeGltfSpec
and writeBinaryGltfSpec
that work fine.
@lasalvavida or @lilleyse, if you have a minute could you briefly look over these tests and see if there is anything I'm obviously missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's because you remove the args to the fake callback, so args[0] is undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am fairly certain spy.calls.first()
accesses the args passed to the function spied on.
See writeGltfSpec
for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing a few console.log
traces, it seems that for some reason the the processFileToDisk
and processJSONToDisk
are resolving before the outputJson
in writeGltf
I'm guessing there is something wrong with my promises
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing there is something wrong with my promises
That is true. Hang tight for a little bit; I'm almost done fixing this
@JoshuaStorm This branch should be clean again |
I'm seeing errors in Travis, but this is clean locally for me |
Ignore the most recent commit, it was off-base I'll look more into this |
I have resolved the Travis failure that occurred due to attempting to write to a directory without the directory first being made. However, this solution is a bit hacky: I want to use both synchronous and asynchronous A simple solution would be just to For example, if I do
and attempt to do My current solution is a bit clunky, and inefficient: I use both |
@JoshuaStorm do the following: fsExtra.outputJsonAsync = Promise.promisify(fsExtra.outputJson);
...
spyOn(fsExtra, 'outputJsonAsync') |
I knew I had to be forgetting something straight forward like that. |
This should be good for review now! |
// Create the output directory if specified | ||
if (createDirectory) { | ||
outputPath = path.join(path.dirname(outputPath), 'output', path.basename(outputPath)); | ||
fsExtra.ensureDirSync(path.dirname(outputPath)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need this because outputJson
will create the dir if it doesn't exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to do this due to writeSource
using fs.writeFile
(not fsExtras), but a better solution is probably just to use fsExtras in writeSource
, so I'll go ahead and do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok, that solution seems good.
var vertexShaderPath = './specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest0VS_Binary.glsl'; | ||
|
||
describe('getBinaryGltf', function() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove line.
Async tests should use expect(promise, done).toResolve(); This is more robust and will keep failing tests from falling through promises. |
@lasalvavida Good catch, I forgot about that. Just to make sure I do these properly: This
should become
Right? Thanks! |
Make sure you don't call I would also write it a little more compactly, like this: expect(writeGltf(gltf, options)
.then(function() {
expect(gltf.shaders.CesiumTexturedBoxTest0FS.extras).not.toBeDefined();
expect(gltf.shaders.CesiumTexturedBoxTest0FS.uri).toEqual('CesiumTexturedBoxTest0FS.glsl');
return fsReadFile(outputFragmentShaderPath);
})
.then(function(outputData) {
expect(bufferEqual(outputData, fragmentShaderData)).toBe(true);
}), done).toResolve(); |
var AttributeCompression = Cesium.AttributeCompression; | ||
var Cartesian2 = Cesium.Cartesian2; | ||
var defined = Cesium.defined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defined
should be at the bottom of this section.
I think |
If node already waits for all promises to terminate, it may be as simple as putting a comment that says that so there's no confusion. |
var fs = require('fs'); | ||
var path = require('path'); | ||
var Promise = require('bluebird'); | ||
var readFile = Promise.promisify(fs.readFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this fsReadFile for consistency with the node guide.
Those are my last few comments; this looks awesome @JoshuaStorm! |
@lilleyse This does change the public API; do we want to merge this now or wait until after the first alpha release? |
I was thinking about this too. It's probably best to wait. I have another question though. Should our public API return promises at all, or should those functions take callbacks? Internally the callback would just wrap around the promise. It seems like callbacks are still the standard for most other node libraries. @mramato do you have thoughts on this? |
Our public API should absolutely return promises. There are two ways to go here:
While 2 wouldn't be a ton of code, it does add some additional overhead and clutter the API a bit. We would also have to add an extra test for every public API function to cover it. My gut says to go with 1 until enough people ask for 2. It would be a non-breaking change to add later. @pjcozzi What do you think? |
Big +1 |
Thanks @lasalvavida and @JoshuaStorm |
Notready for review.I am currently switching some files to be
Promise
s instead of using callbacks, but I've hit a few snags which have resulted in me doing some anti-patterns that I wanted to ask a few questions about to resolve.I'll be adding inline comments so it is easier to see what I am talking about.