Skip to content
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

Proposal: replace callbacks by Promises #74

Open
Chnapy opened this issue Dec 26, 2019 · 3 comments
Open

Proposal: replace callbacks by Promises #74

Chnapy opened this issue Dec 26, 2019 · 3 comments

Comments

@Chnapy
Copy link

Chnapy commented Dec 26, 2019

Hi,

I was wondering if there is any reason Easystar should not use Promise objects. My idea is that instead of using callbacks given to findPath(), the function calculate() would simply return an array of Promise (one for each path).

The only concern I see is the ES6 requirement, but Babel is here for that.

Promises are used today in a lot of libs and apps, they are normalized and quite easy to use. In my app I wrap the callback in a Promise, what is not very elegant.

I can do a PR, I just want some returns before digging the code.
What do you think ? :shipit:

@prettymuchbryce
Copy link
Owner

Hey Chnapy. I think it's a good idea. This library was written before Promises were standardized in JavaScript.

Introducing native promises would be a breaking change. So I think it should be introduced as part of 1.x.x.

I am open to hearing proposals about how the API would be affected by this change.

One thing that comes to mind. Currently findPath returns an instanceId which can be used to cancel the path calculation. If findPath instead returns a promise, how do we handle canceling the path calculation?

@Chnapy
Copy link
Author

Chnapy commented Dec 30, 2019

Hi !

Thanks for your answer, I see the 'cancel' problematic.
I see 2 solutions:

The first one
In my side, my wrapper returns a list of PathObject which is composed by the promise, and a cancel() function:

export interface PathObject {
    promise: Promise<Position[]>; // Position = {x,y}
    cancel: () => boolean;
}

So calculate() would return a list of this PathObject in which cancel() would cancel the calculation. The change would not be so hard, but the initial logic changes maybe not for the better.

The second one
As I see, Easystar store its instances in an object instances following this type:

var instances: {
  [id: number]: Instance;
};

My suggestion is to instead use a Map. Maps can have objects as keys, like Promises. In maps the object key check is done by reference, not by value.

var instances: Map<Promise, Instance>;

So now we can do this:

finder.findPath(startX, startY, endX, endY);

const promises = finder.calculate();

// On first path done, do something
promises[0].then(path => console.log(path));

// I want to cancel the first path
finder.cancelPath(promises[0])

I cancel the path calculation by simply giving the promise itself.

I like this solution, it keeps the initial logic, and I find it quite elegant. But the type change of instances may be too much ?

@pkaminski
Copy link

A better option might be to dynamically add a cancel() method to the promise being returned, which could capture the id and invoke cancelPath when called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants