Giter VIP home page Giter VIP logo

yaku's Issues

Does not work on UC Browser

The following code is not working in UC Browser, because this is undefined inside an IIFE in UC Browser.

function(module, exports, __webpack_require__) {

	/* WEBPACK VAR INJECTION */(function(global) {var Yaku = __webpack_require__(/*! ./yaku */ 80);

	try {
	    global.Promise = Yaku;
	    window.Promise = Yaku;
	} catch (err) {
	    null;
	}
	/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))

/***/ }

Pass data (callback) to unhandledRejection handler

I have a case, when I need pass callback to unhandledRejection handler and can't use catch in default maner, when I try define property for the promise, I notice that property do not passed in promise at onUnhandledRejection, how I can implement this behaviour?

Example:

const onUnhandledRejection = (reason, promise) => {
  // promise.handleRejection always undefined
  if (promise && typeof promise.handleRejection === 'function') {
    promise.handleRejection(reason);
  } else {
    console.error(reason);
  }
};

window.onunhandledrejection = ({ reason, promise }) => {
    onUnhandledRejection(reason, promise);
};

const handleRejection = (promise) => {
  Object.defineProperty(promise, 'handleRejection', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: (reason) => {
      if (reason && reason instanceof SkipError) return;
      console.error('MIDDLEWARE ERROR:', reason, reason.stack);
      // ...customize global rejection handler for this promise
    }
  });

  return promise;
};

handleRejection(promise(client)).then(
  (result) => {
    // ...
  },
  (error) => {
    throw SkipError;
  }
);

Documentation for `async`

I think the documentation for .async is very misleading since it says:

An throttled version of Promise.all

A lot of people, in my experience answering questions in StackOverflow, being involved in the spec process and helping maintain a library is that a lot of people mix up the fact a promise is a proxy for the value of an already started operation.

A throttled Promise.all is impossible of course since all the inputs to .all are already promises which means the operations themselves have already started.

It would be useful to update the documentation to reflect that, also it would be nice if the docs were moved to an API.md file or something similar.

Mock Mode

Hi,

We use Yaku for production and had a need for a mock mode to allow synchronous tests.

I hacked it in:
https://github.com/lukeapage/yaku-mock

If I cleaned it up, abstracted and made a PR back to you, would you be interested? or should I keep it as a fork?

`then` memory leak

If we call a promise's then method multiple times, it may potentially cause memory leak:

var p = Promise.resolve();

p.then(function () {});
p.then(function () {});
p.then(function () {});
p.then(function () {});
p.then(function () {});

process.on('exit', () => {
    p = null;
});

If we don't release variable p, its children promises will stay in memory even after p and all the children are settled. What we should do with this situation is not specified in the ES6 yet.

I think we should cut off the link between the parent and child immediately after the child is settled.

Finally swallows rejections

If I call finally on a rejected promise it unexpectedly becomes fulfilled.

const Promise = require(process.argv[2]);

const p = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('simulated error')));
});

p.finally(() => {
  console.log('Cleanup');
})
.then(result => {
  console.log('Unexpected success', result);
})
.catch(err => {
  console.error('Expected failure', err);
});

With yaku:

$ node index.js yaku
Cleanup
Unexpected success Error: simulated error

With bluebird:

$ node index.js bluebird
Cleanup
Expected failure Error: simulated error

Your finally test doesn't catch this because although you expect 'error' here: https://github.com/ysmood/yaku/blob/master/test/finally.js#L28

You do not confirm that its a rejection here: https://github.com/ysmood/yaku/blob/master/test/testSuit.js#L14

The cause is that you do not rethrow or wrap value with Promise.reject here:

return value;

Bind to Angular 1.x digest?

Bluebird provides the Promise.setScheduler method to bind with the angular digest cycle.

// This will synchronize bluebird promise queue flushing with angulars queue flushing
// Angular is also now responsible for choosing the actual scheduler
Promise.setScheduler(function(fn) {
    $rootScope.$evalAsync(fn);
});

Can the same thing be achieved with Yaku?

Promisify ReadStream

Such as

var utils = require('yaku/lib/utils');
var f = fs.createReadStream('test');

var p = utils.promisify(f);

p.then(function (data) {
    console.log(data);
})

global.Promise should be non-enumerable and should have correct name property

Expected:

> Object.getOwnPropertyDescriptor(global,'Promise');
{ value: [Function: Promise],
  writable: true,
  enumerable: false,
  configurable: true }

> global.Promise.name
'Promise'

Actual:

> Object.getOwnPropertyDescriptor(global,'Promise');
{ value:
   { [Function]
     default: [Circular],
     resolve: [Function],
     reject: [Function],
     race: [Function],
     all: [Function],
     Symbol: [Function: Symbol],
     speciesConstructor: [Function],
     unhandledRejection: [Function],
     rejectionHandled: [Function: en],
     enableLongStackTrace: [Function],
     nextTick: [Function: nextTick],
     _s: 1 },
  writable: true,
  enumerable: true,
  configurable: true }

> global.Promise.name
''

Bug: Stealing a resolver and using it to trigger reentrancy

var Promise = require("yaku");
var assert = require('assert');

var stolenResolver;
var StealingPromiseConstructor = function StealingPromiseConstructor(resolver) {
	stolenResolver = resolver;
	resolver(
		function () {},
		function () {}
	);
};
var iterable = {};
var atAtIterator = '@@iterator'; // on firefox, at least.
iterable[atAtIterator] = function () {
	stolenResolver(null, null);
	throw new Error(0);
};
assert.doesNotThrow(function () {
	Promise.all.call(StealingPromiseConstructor, iterable);
});

It throws this:

AssertionError: Got unwanted exception.
Actual message: "self.reject is not a function"

This test was taken from es6-shim -- https://github.com/paulmillr/es6-shim/blob/4a815033b35a051632e035e1ec95aa3b1b43bfdd/test/promise/simple.js#L34-L51

Convert coffee to js

It will decrease the code base a little, and make it more friendly for beginners.

Yaku doesn't work if div with id="process" exists

This is the weirdest glitch I've found in my entire existence.

If you add a <div id="process"> to the DOM, it breaks.

The problem is that Yaku checks for window.process, which seems to be defined in some browsers as $("#process"). Yaku then tries to use process.nextTick, which of course doesn't exist.

This doesn't happen in all browsers; not sure why.

Incorrect promise when calling `resolve` twice

Here is an edge case bug that we found in our production code. In the new Promise() constructor, if the resolve callback is called twice with another promise, then the second call to resolve overwrites the first call. A simple test case:

//comment out this line to test native version
const Promise = require('yaku');

const firstValue = Promise.resolve('correct');
const testPromise = new Promise(resolve => {
  resolve(firstValue); //first resolve another promise
  resolve('wrong'); //then resolve a value
});
//this line should log `correct`, but logs `wrong`
testPromise.then(x => console.log(x));

This only seems to happen when firstValue is a promise, when it's just the string 'correct' the code works the same as the native Promise implementation.

As I said at the beginning, this is an edge case bug, as calling resolve multiple times is not good, but we had an issue with this in production (we use polyfill.io for IE11 support), so I thought I'd at least let you know of the issue.

Docs about utilities, and utilities

Hey, the docs say that the library does not offer things like .done, but it appears it just exposes a (differently named) .end instead.

I warmly recommend the following:

  • Remove .defer, deferreds are super problematic anyway, they were decided against in the official API for the Zalgo problem they cause.
  • Remove .end, you have unhandled rejection detection already - that's better anyway.
  • Don't expose .isPromise, that encourages (in my experience) users to rely on it instead of Promise.resolveing results.
  • Move source to another unrelated repo, it is practically a mini observable. It's worth documenting separately.
  • Don't show examples in the docs that throw non-Errors as that breaks stack traces, as a library that implements long stack traces I assume you care about that.

Callbackify won't callback if the callback is the only argument

This prints done as expected:

callbackify(function() {
  return Y.resolve('a');
})(1, function() {
  return console.log('done');
});

while this does not:

callbackify(function() {
  return Y.resolve('a');
})(function() {
  return console.log('done');
});

The only difference is the first example passes an extra (unused) argument to the function returned by callbackify.

instance constructor is not Promise

I'm using promise.prototype.finally to add the finally functionaity to Promises, but that depends on the promise's constructor to be Promise. Currently the constructor is Object.

> (new Promise(function() {})).constructor
Object() { [native code] }

IE compatibility

You use Error#stack quite a bit in the code which was only supported by IE10+

handled rejection can not be recognized

When I use catch or the second argument of then to handle a rejection, Unhandled Rejection is always shown.

yaku = require 'yaku'
new yaku (resolve, reject) ->
    reject 1
.catch ->

the result is

Unhandled Rejection: 1

I think this bug is introduced in v0.2.0

A better default onUnhandledRejection handler

console.trace is not a good enough way to show stack trace. Also, uglified code make it pretty difficult to debug.

Unhandled rejection Error: [TypeError: Cannot read property 'value' of undefined]
Trace
at Function.t.onUnhandledRejection (/usr/local/lib/node_modules/nokit/node_modules/nofs/node_modules/yaku/dist/yaku.js:6:822)
at /usr/local/lib/node_modules/nokit/node_modules/nofs/node_modules/yaku/dist/yaku.js:6:2168
at r (/usr/local/lib/node_modules/nokit/node_modules/nofs/node_modules/yaku/dist/yaku.js:6:1171)
at process._tickCallback (node.js:442:13)

Something strange (Slow resolve on pageload)

Hello hello

First things first, i like your library โค๏ธ ๐Ÿ™‰ , it provides huge benefits compared to other promraries (promise-libraries ๐Ÿ˜„)! Mainly its size is a really killer feature! But the longStackTraces are a good thing too.

But now I found a very strange problem: As soon as I use Yaku with rollup or brunch (yes I tried both), I notice a very long wait time from resolve to then. It is loading and loading, while a bluebird promise which was started in the same time as yaku, already has resolved.

dec 25 2016 10-14 pm - edited

(When I try yaku promises after the page is fully loaded, it works without problems, this slow resolve only happens on pageload)

Do you have an idea?

This is the code:

Yaku.resolve().then(function() {
  console.log('yaku1')
})

Yaku.resolve().then(function() {
  console.log('yaku2')
})

bluebird.resolve().then(function() {
  console.log('bluebird')
})

One thing I noticed too is, that when I console.log(Yaku) this log takes the same time to complete as the Yaku resolves! It is very strange: first the log just outputs function, and then it magical changes the function to:

function Promise(executor) {
        var self = this,
            err;

        // "this._s" is the internal state of: pending, resolved or rejected
        // "this._v" is the internal value

       โ€ฆ

This is the rollup config I used:

var flow = require('rollup-plugin-flow');
import babel from 'rollup-plugin-babel';
var serve = require('rollup-plugin-serve')
var path = require('path')
import nodeResolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';

export default {
  entry: 'app/main.js',
  dest: 'app/assets/bundle.js',
  plugins: [ flow(), nodeResolve({
        jsnext: true, main: true
      }), commonjs(), serve({
    contentBase: path.join(__dirname, 'app', 'assets')
      }) ],
  format: 'umd'
};

long stack traces

Are there any benchmarks which say what the trade-off is with using long stack traces?

Thanks

difference between return Promise.reject(x) and throw x

I can track down further if its not obvious but I've been trying to work out why I get unhandled rejections for promises that are handled. I've not been able to make a reduced test case, but the behaviour seems to occur when I have something like

promise.catch(() => {
    // maybe do something different
    return Promise.reject({});
}).catch(() => {
    // absorb rejection so unhandledrejection should not be called
});

and it appears changing the return to throw make it work and not give unhandled rejections (which is the expected behaviour).

promisify

Hey, if you want node usage, it would be immensely useful to support promisify natively. Without the library supporting it itself, it is impossible to make promisify comparably fast.

See bluebird's https://github.com/petkaantonov/bluebird/blob/master/src/promisify.js for inspiration :)

I saw you already have a promisify.js file, but it is slow (uses a closure and .slice).

A promisifyAll would also be immensely useful for server side use.

Support global unhandled rejection detection events

Basically https://gist.github.com/benjamingr/0237932cee84712951a2

Most promise libraries and native promises in NodeJS support the global rejection events, these events in NodeJS allow code using multiple promise libraries and native promises in the same project to handle rejecitons globally and uniformally throughout the application and to provide a useful hook.

It also makes switching libraries simpler.

It would be great if Yaku could support it, I don't mind writing the PR but I think that you already know how to :)

utils aync strategy problem

This issue is inspired by the exercise, as described in the test case of this exercise, when the throttled-promise handler get all it's tasks done, the saveResults should keep their order as they are the result of each one of list

async: (limit, list, saveResults, progress) ->
  ...

Also, I modify one existed test case of yours, to show the difference.

test 'async array', [1, 2, 3], ->
  list = [
    -> utils.sleep 90, 1
    -> utils.sleep 10, 2
    -> utils.sleep 10, 3
  ]

  utils.async 2, list

The old version will get [2, 3, 1] instead of [1, 2, 3].

And there is a pull request. I hope myself get this right.

incorrect behavior with unhandledrejection events

Per https://github.com/ysmood/yaku/blob/master/docs/debugHelperComparison.md#better-unhandled-error, Yaku will not fire an unhandledrejection event in this case:

p0 = Yaku.resolve().then(function () {
    abc()
})
p1 = p0.then(function () {})
p2 = p0.then(function () {})
p3 = p0.catch(function () {})

From my understanding, this is incorrect behavior. p1 and p2 are new promises that have unhandled rejections.

I think the following should happen:

window.onunhandledrejection = ({promise}) => { 
  console.log('window.onunhandledrejection: p' + promises.indexOf(promise));
}
p0 = Yaku.resolve().then(function () {
    abc()
})
p1 = p0.then(function () {})
p2 = p0.then(function () {})
p3 = p0.catch(function () {})
promises = [p0, p1, p2, p3]

// should log 'unhandledrejection: p1'
// should log 'unhandledrejection: p2'

I believe Chrome actually implements the spec correctly.

Can't register global unhandled rejection

i try to add a handler for all unhandled rejection:
window.onunhandledrejection = ({ reason, promise }) => { console.log('help');};
Promise.reject(new Error("ERR"));

The only output i can see is the default 'Potentially unhandled rejection [1] Error: ERR'.
Is it a bug or am i using it wrong?

"hash" util/helper request

Could we add a hash helper like the RSVP, I think it's very convenient and useful? You think that is OK with you? Maybe I could implement it myself and make a PR.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.