Open colelawrence opened 10 years ago
Hmm.. are you looking for arbitrary properties that will be passed from Builder
to Request
? Can you help me understand how you'd use them? And would setters that expect curried callbacks be more useful?
Looking further into the source code, I am curious as to whether I can actually build up a long builder for a series of tasks to be executed. I am using phantom to login to a website, then use the obtained session cookies to perform actions. Does fluent-phantom have an queing system like jQuery Effects?
It does not today. Supporting more complex click path simulations would be nice, but probably a big change to the API. Could you write up some pseudo-code for how you'd like to see it work?
On Tuesday, July 15, 2014, Cole R Lawrence notifications@github.com wrote:
Looking further into the source code, I am curious as to whether I can actually build up a long builder for a series of tasks to be executed. I am using phantom to login to a website, then use the obtained session cookies to perform actions. Does fluent-phantom have an queing system like jQuery Effects http://api.jquery.com/category/effects/?
— Reply to this email directly or view it on GitHub https://github.com/rawg/fluent-phantom/issues/3#issuecomment-49029670.
Jeremy Fisher jeremy@rentawebgeek.com | @thisisroot https://twitter.com/thisisroot | www.linkedin.com/in/jeremiahcfisher
Due to time sensitivity, I am using nightmare for my project, so after some research I'll have a lot better understanding of how this would be implemented.
I wouldn't initially think that fluent should use nightmare's pattern though.
First thoughts are that fluent would behave more similarly to promises, because promises are fairly fluent and a common pattern in JavaScript. Promises with database querying.
When I initially opened #4, I had promise error handling in mind.
So, I've been learning about Promises and I think that there would be a benefit to using them in this project. I made this gist of a file reading copying, and manipulating api that relies on the core idea of Promises. file-promise-api
In essence, we would extend a class like this: Promise Keeper I wrote.
This would mean that there wouldn't be a Builder
when using promises, and the promises are fired as they are added.
For Example:
phantom = require 'fluent-phantom'
# Here we create the page in our PhantomPromise class
phantom.promise()
# load promise resolves after onPageLoad
.load("http://google.com")
# Inject promise resolves after script is loaded
.inject("//cdnjs.cloudflare.com/ajax/libs/zepto/1.1.4/zepto.min.js")
# Evaluate promise resolves after we get our return value
.evaluate ->
Zepto("button").click()
# Expecting that the last evaluate clicked some buttons it should allow us to log those buttons
.log "buttons:"
#> [<button .../>]
# Wait for any page load actions to complete
.run (page, done) ->
page.set("onLoadFinished", done)
# would print the result of done() because that was the last object in the chain.
.log "status"
Nightmare looks pretty nice for automating long click paths – it wasn't around when I started this.
This is a great use of promises (which are a good way to cut down callback hell whether you're working in JavaScript or something fancier like Akka!). I'd thought about rewriting this as a series of promise-returning decorations to the node-phantom proptotypes, but haven't had the hammock time to reason through the API yet. I think that approach is worth pursuing, and should include your .run(..., done)
idea and related trappings.
I updated the promise-keeper.coffee class so that .set(name, [value])
and .get(name)
function as I described above.
# Promises
# Use Request from index
{ Request } = require './'
{ PromiseKeeper } = require './promise-keeper.coffee'
{ Deferred } = require 'promise.coffee'
fs = require 'fs'
nodeStyleLift = (nodefn) ->
->
def = new Deferred
args = [].slice.call arguments
args.push (err, res) ->
if err? then def.reject(err) else def.resolve(res)
->
nodefn.apply this, args
return def.promise
readFileAsync = nodeStyleLift fs.readFile
pk = new PromiseKeeper()
pk
.then readFileAsync('package.json', 'utf8')
.set 'package.json'
.then readFileAsync('promise-keeper.coffee', 'utf8')
.set 'promise-keeper.coffee'
.get 'package.json'
.log("Package Json")
.get 'promise-keeper.coffee'
.log("Promise Keeper")
.then null, (err) ->
console.err err
This code logs the contents of package.json
before logging the contents of promise-keeper.coffee
, even though each file was read at different times.
In a project I'm working on, I am passing a builder object to various functions that apply different actions to it before executing.
So in my set-up I sign-in as a user, then I open a project, then I want to apply configurations to that project. Applying a
project-name
variable setter in the builder when this is set-up:fluent_OpenProject(builder, "Apples-Oranges")
will allow me to callfluent_DeleteProjectFile(builder, "readme.md")
without passing the project name again (which is required for URL construction).I would imagine that there could be other applications for this, and it wouldn't be too hard to implement.
Thanks