kriskowal / q Goto Github PK
View Code? Open in Web Editor NEWA promise library for JavaScript
License: MIT License
A promise library for JavaScript
License: MIT License
Great new README! It would have really helped me dive into q easier. I'm wondering if it makes sense to give a quick intro into the problem q helps solve. Here is a shot at it, but probably needs a bit of massaging, feel free to disregard too if I got the overall message wrong.
If a function cannot return a value or throw an exception without blocking, it can return a promise instead. A promise is an object that represents the return value or the thrown exception that the function may eventually provide. A promise can also be used as a proxy for a remote object to overcome latency.
So, instead of writing code like this:
asyncCall1(function (value1) {
asyncCall2(value1, function(value2) {
asynCall3(value2, function(value3) {
asynCall4(value3, function(value4) {
//Do something with value4
});
});
});
});
You can write code like so:
q.call(asyncCall1)
.then(asyncCall2)
.then(asyncCall3)
.then(asynCall4)
.then(function(value4) {
//Do something with value4
})
.end();
with the added benefit of being able to let errors propagate to top level error handlers. Focus more on your code logic and less on handling function callbacks.
Calling nextTick
is good for letting other parts of application to execute, but it may cause nonobvious problems when dealing with streams in node.js.
For example, creating ReadStream and then using it after resolve
will end up in skipping some "data"
events on it, because we skipped one event-loop tick.
In q-fs/lib/q-fs it's using q/util instead of q/.
Also in q-fs/lib/common.js
We need a way to run tests in browsers to validate the releases. @Gozala’s CommonJS unit test suite work great in Node.
We must have a solution that works for both browsers and Node. I would accept a temporary solution that ports the tests to Jasmine or something. I would accept a solution that embeds a mini module loader to run the tests client-side.
I tracked down the hangs. It happens because nbind
uses callback.bind.apply(callback, args)
, and some browsers don't have bind
.
This isn't a big deal. But we should fix it. First off, the test runner needs timeout support so this doesn't confuse us again, so I'll try adding that. Although, why isn't it just failing? A bit strange. Will investigate.
The question for discussion is, do we want to support nbind
et al. in old browsers, or not? I can vaguely see the argument for someone wanting to use these methods in non-Node contexts. But they are named specifically for Node (where bind
is always available). So we could either:
nbind
to not use Function.prototype.bind
, thus allowing nbind
et al. to be used in old browsers.if (Function.prototype.bind)
or similar, so that they don't even run in old browsers.I think the API and Advanced API sections would be best as separate wiki pages, linked from the README.
I'm torn between keeping the beautiful new tutorial in the README or moving it to the wiki and having a really slimmed-down README.
Sorry if this is an simple question, I'm new to promises/futures.
I'm using the mongodb driver, and I need a recursive function to simulate joins on a table, the pseudocode woudl look like
function collectColumnNames(collectionName, columnNames )
{
foreach ( row in collection )
{
foreach ( column in row )
{
if ( column is lookupColumn ) collectColumnNames(column.name, columnNames );
else columnNames.push(column.name );
}
}
}
But of course because this is asynch I'm not getting all the column names.
How can I use Q to solve this problem ?
Thanks!
Charlie
With the addition of Q.bind
, and all the recent discussion of Q.call
, I'm feeling like Q.node
really should be Q.nbind
. Thoughts?
Do we need/want a Q.napply
? I haven't found a use case for it, ever, but it would complete the set.
When running in Opera browser:
Error thrown at line 7, column 622 in <anonymous function: l>(a) in http://localhost:8080/workspace/www/q.min.js:
B.port2.postMessage()
called from line 6, column 47 in g(a, b, d) in http://localhost:8080/workspace/www/q.min.js
called from line 6, column 882 in v(a) in http://localhost:8080/workspace/www/q.min.js
I know stack is not helpful :) Assuming you will test source in Opera ;)
The documentation needs to be improved to make it clearer that all callbacks occur in separate events. See #29.
This is just a thought, feel free to disagree with me, but I'd just like to throw the idea out there.
I have a suspicion, that once yield is available in more environments (I'm currently writing a shim to compile it to ECMA5 based on the current standards) we'll see lots of methods that look like the following.
var sumOfStuff = Q.async(function(a,b,c,d,e,f,g,h){
a = yield a;
b = yield b;
c = yield c;
d = yield d;
e = yield e;
f = yield f;
g = yield g;
h = yield h;
var other = yield someRemoteData({id:a});
Q.return(other+b+c+d+e+f+g+h);
});
That is to say, lots of functions will begin by yielding on all their arguments, either one at a time, or using something like Q.all.
What might be preferable, would be to resolve all promises that are passed as arguments, before giving them to the function. The only down side, is that it prevents you from writing functions like:
var hash = Q.async(function(pass){
var salt = getRandom();//computationally expensive
Q.return(salt + yield pass);
});
Perhaps we could have some way of annotating the function as lazy
but resolve all arguments by default?
Not sure what you want to do with them, exactly, but currently it uses lots of nonexistant methods from a util
module, something about a "view" experiment, etc.
<html>
<head>
<script src="../../lib/q/q.js"></script>
<script>
// Accept a promise for load, and report the success or failure of the load
function foo(loaded) {
return Q.when(
loaded,
function glory(loaded){
// Ooops the processing of success path fails!
throw new Error("You lose");
console.log("We have ", loaded);
},
function fail(err) {
console.error("We have "+err);
}
);
};
// Create a promise for a load
function promiseLoaded() {
var defer = Q.defer();
window.addEventListener(
'load',
function(event) {
defer.resolve("success");
},
false
);
return defer.promise;
}
function main() {
// foo returns a promise, but we don't look at the return so we lose.
foo(promiseLoaded());
}
main();
</script>
</head>
<body>
<h1>Bad developer ergonomics: throw in promise fulfillment swallows exception</h1>
<p>May be related to <a href="https://github.com/kriskowal/q/issues/23">Issue 23 on github q</a>
</body>
</html>
See this gist and comments for details: https://gist.github.com/1723027
In my implementation (which learns a lot from q) i modified the specified code about how reject wrapping works :
Then the result is right, am i making a mistake?
i have a array like [1,2,3],after i do invoke the resolve function like xx.resolve(the_array), the array data change to [1,2,3, reduce: [function...]]
i think the ploblem is occur by this code in q.js:
var reduce =
Array.prototype.reduce =
Array.prototype.reduce || function (callback, basis) {
for (var i = 0, ii = this.length; i < ii; i++) {
basis = callback(basis, this[i], i);
}
return basis;
};
the right way maybe this:
var reduce =
Array.prototype.reduce || (Array.prototype.reduce = function (callback, basis) {
for (var i = 0, ii = this.length; i < ii; i++) {
basis = callback(basis, this[i], i);
}
return basis;
});
I have added "event-queue" package to the npm that wraps process.nextTick
to the require('event-queue').enqueue
. By adding it to the dependencies in package descriptor promises can take advantage of process.nextTick
on node, which is much more efficient.
I'll create a pull request from this commit:
http://github.com/Gozala/q/commit/5aafc6bad5a4e858d2f0421937af41ae11a9a187
Since this changes dependencies property it will have to wait before
http://github.com/kriskowal/q/pull/1
is in
This behaviour is rather unintuitive. Is this by design?
Here is an example:
Q.when(Q.deep(new Date()), function(ret) {
console.log(ret);
});
===> {}
whereas
Q.when(new Date(), function(ret) {
console.log(ret);
});
===> Sat, 29 Jan 2011 10:23:24 GMT
I have an issue when processing and array of promises. I need the ability to catch all the results on fin no mater if they fail or not and examine the results.
This is kind of an optimistic asynchronous execution. Since "all" fires fail if any of the promises fails I propose the addition of "some" handler. "some" could resemble all but would be something like this:
function some(promises) {
return when(promises, function (promises) {
var countDown = promises.length;
if (countDown === 0)
return resolve(promises);
var deferred = defer();
reduce.call(promises, function (undefined, promise, index) {
fin(promise, function () {
promises[index] = promise;
if (--countDown === 0)
deferred.resolve(promises);
})
}, void 0);
return deferred.promise;
});
}
I would like your opinion before I issue a pull request.
Cheers,
utvara
Hi Kris, I see that after util.js was merged into Q, the methods Q.join and Q.deep were completely removed.
Is it by purpose or will you reintroduce them soon? So far we must stick with 0.3.0 because of that.
Thanks for your great work, it is the best Promise library in JS!
Cancellation is tricky.
Mark Miller argues that we should not add cancellation at all. On the flip side, most people feel the need for it, including @domenic and @IgorMinar. If cancelation is a mistake, it is an oft-made mistake.
Consider a naïve cancelable promise.
function service() {
// start work…
var deferred = Q.defer(function cancel() {
// …stop work
});
deferred.promise;
}
var promise = service();
clientA(promise);
clientB(promise);
There is a hazard in this case. Either clientA
or clientB
might call promise.cancel()
and thus interfere with the other client’s progress. With your face close to the page, it looks like the problem is that we need a way to count how many services depend on the promise. From a higher perspective, cancelation is inherently hazard prone.
The philosophical reasoning behind banning cancelation outright is that a cancelable promise must necessarily have all of the power of a deferred, nullifying the (POLA) advantage of separating the promise
part from the resolve
part. Anyone with a cancelable can call cancel(), which is effectively equivalent to preemptively rejecting the promise (resolving the promise with a rejection).
So, Mark argues, if you want something to be cancelable, just return the whole deferred to make it clear that you’re granting both powers. “Similar things should either be very different or the same” — Mark Miller attributes this paraphrase to Alan Kay.
In this example, the promise can be cancelled by rejecting the deferred.
function delay(ms) {
var handle = setTimeout(deferred.resolve, ms);
var deferred = Q.defer();
Q.catch(deferred.promise, function () {
clearTimeout(handle);
});
deferred;
}
var deferred = service();
clientA(deferred);
clientB(deferred);
deferred.reject(new Error("Cancelled”));
This at least demonstrates the critical insight that, regardless of how cancelation looks, this is certainly how it should work. It does not inherently solve the problem of tracking how many parties remain interested in the result.
However, there is a story on graceful migration that this does not address. Expressing that you are no longer interested in a result is orthogonal to expressing that you are able to cancel work if no one is interested any longer in the result. I posit, it should be possible to go through either side of this extra effort independently. That is, a cancelable should have the same interface as a promise, albeit all the powers of a deferred, but also, all promises should have the interface of a cancelable, even if they do not provide that power. As such, it would be possible for a service provider to add cancelability to a promise before or after a service consumer adds support for proactively canceling promises that they no longer need.
Down this track of thought, promises would have a cancel()
method which would be a NOOP. A cancelable
would be a new type of object entirely, that has the interface of a promise and the powers of a deferred. A cancelable would have a functioning cancel()
method. All of the promise-like methods of a cancelable would return new, normal promises, and cancelation would not implicitly propagate. Cancelables could be constructed from deferreds, like Q.cancelable(deferred).
The cancelable
solution might not stick since it would obviate chaining. Each step of the promise chain would have to be replaced with an explicit mechanism for how to forward cancelation. We’d have to explore some code samples to see whether it would be worth dealing with, and whether we might find ways to make it easy to flag common policies.
For either approach, using a deferred or a cancelable, there is the independent problem of tracking how many parties are still interested in the result of a promise and actually canceling only when that drops to 0.
Ideally, we could involve the garbage collector since it does this work already. We could use a WeakRef
, or any mechanism that notifies the application after an object has been garbage collected. We could use this mechanism to implicitly cancel any promise for which there are provably no observers. However, we do not live in a world with WeakRef
, and such would only work if the promise library were to exist in a privileged context, possibly served to unprivileged contexts.
In the real world, we would have to do reference counting in application-space. One thought would be to add a fork()
function to a cancelable. The cancelable could contain an internal counter of how many forks exist and each fork could decrement that number exactly once. When they drop to zero, the cancelable could commit to stopping work.
This should be an accurate summary of every discussion I’ve had on the topic as-yet. Please chime in.
asap
is broken because of the misbehavior of isResolved
. require('q').isRelsolved(null)
will throw because null.valueOf() will throw.
Alex Raschmeyer recommends that we reconsider the name of the node callback function.
http://www.2ality.com/2012/04/expand-urls.html
For what it’s worth, the callback could always be the same object and thus it would make sense for it to be a property rather than a function, but it would incur the cost of generate such a function for every deferred. That is why it is a function. Alternate approaches could simulate a property in some cases.
Although I try very hard to avoid letting success values or rejections fall on the floor, I keep screwing up, and it seems like Q could help make it more obvious when I am screwing up.
The defer() resolve() implementation knows when it is being resolved with no one around to hear because pending will be empty. I propose adding some kind of optional reporting in this case. This would allow my testing framework to both notice when:
Obviously, there needs to be a way to actually "cap" the chain of promises. The current end() method does this in spirit, but I believe will still result in resolutions with an undefined value. (OTOH, undefined could just be made special in that it does not trigger the reporting logic.)
I recognize that there are two use-cases that would not be happy about this happening all the time:
The solution to both those problems is that this would be opt-in. Either you could provide a custom handler, or invoke "$Q.forBabies()" which would just throw, thereby relying on node's/the browser's built-in stuff.
True promise-wrappers for callback-style functions should also handle promises as an arguments.
Example below should work, but breaks with an error:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Bad argument
at Object.open (fs.js:224:11)
at new <anonymous> (fs.js:1056:6)
at Object.createReadStream (fs.js:1010:10)
at Object.readFile (fs.js:78:23)
at Object.apply (/usr/local/lib/node_modules/q/q.js:395:27)
at Promise.promiseSend (/usr/local/lib/node_modules/q/q.js:243:41)
at Array.0 (/usr/local/lib/node_modules/q/q.js:632:28)
at EventEmitter._tickCallback (node.js:192:40)
Example:
var Q = require('q'),
FS = require('fs');
Q.ncall(FS.readFile, FS, Q.ref(__filename))
.then(function(c) {
console.log(c);
})
.end();
https://github.com/kriskowal/q/blob/master/q.js#L732 seems to reference a nonexistant values
variable.
I'm struggling with this question: http://stackoverflow.com/questions/10545087/how-to-use-module-q-to-refactoring-mongoose-code
I hope there are some examples in the wiki.
If promise is rejected, it's chained promise also get's rejected but it also gets resolved with a rejection reason.
For reproducible scenario see http://github.com/kriskowal/q/pull/1#L3R41
q.all with an empty array should execute the success function.
Readme contains description of Q.allResolved method, but last version in npm (0.8.2) doesn't.
There have been major API changes that haven't been reflected in the README.
I wasted a couple hours this weekend trying to figure out what I was doing wrong.
I usually just RTFC, but the docs were just so good that I didn't think I needed to ;)
Oh well ^_^
Thanks!
I am using Q in mozilla addon sdk which parses for static requires in order to authorize loading a module dependency from a module.
Problem is serverSideRequire("event-queue")
which is not detected (as indended).
The best solution that does not interfere with the current requirements seems to be injecting the nextTick
implementation.
Could we add something like Q.nextTick which I can set externally and use that over fallbacks?
I often find myself wrapping Node-style API methods in promises, and doing something like the following:
var def = Q.defer();
doSomething(a, b, function(err, result) {
if (err) {
def.reject(err);
} else {
def.resolve(result);
}
});
return def.promise;
It would be great if I could do this instead:
var def = Q.defer();
doSomething(a, b, def.callback());
return def.promise;
Would that be possible?
can we get an npm publish please? I am in need of the fix for q.all on empty arrays.
There is an error in Q.npost()
and Q.ninvoke()
, they should pass object
as a second argument to napply()
, not name
.
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback with a given array of arguments, plus a provided callback.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param {Array} args arguments to pass to the method; the callback
* will be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
exports.npost = npost;
function npost(object, name, args) {
return napply(object[name], object, args);
}
/**
* Calls a method of a Node-style object that accepts a Node-style
* callback, forwarding the given variadic arguments, plus a provided
* callback argument.
* @param object an object that has the named method
* @param {String} name name of the method of object
* @param ...args arguments to pass to the method; the callback will
* be provided by Q and appended to these arguments.
* @returns a promise for the value or error
*/
exports.ninvoke = ninvoke;
function ninvoke(object, name /*, ...args*/) {
var args = array_slice(arguments, 2);
return napply(object[name], object, args);
}
I'd like to use this issue to document the well-known problem with Q stack traces, and as a place to discuss any progress I can make toward improving it. I'm currently investigating the V8 stack trace API as a possible help.
Consider the following code:
"use strict"; // 1
var Q = require("q"); // 3
function doXAsync() { // 5
return Q.resolve(5); // 6
}
function doYAsync() { // 9
return doXAsync().then(function () { // 10
throw new Error("boo!"); // 11
});
}
function doZAsync() { // 15
return doYAsync(); // 16
}
doZAsync().end(); // 19
Currently this prints the following stack trace:
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: boo!
at c:\Users\Domenic\Programming\test\test.js:11:15
at _fulfilled (c:\Users\Domenic\Programming\test\node_modules\q\q.js:542:32)
at makePromise.promiseSend (c:\Users\Domenic\Programming\test\node_modules\q\q.js:257:37)
at c:\Users\Domenic\Programming\test\node_modules\q\q.js:564:18
at makePromise.promiseSend (c:\Users\Domenic\Programming\test\node_modules\q\q.js:257:37)
at Array.0 (c:\Users\Domenic\Programming\test\node_modules\q\q.js:557:24)
at EventEmitter._tickCallback (node.js:192:40)
Ideally it would print something more like
Error: boo!
at c:\Users\Domenic\Programming\test\test.js:11:15
at doYAsync (c:\Users\Domenic\Programming\test\test.js:10:xx)
at doZAsync (c:\Users\Domenic\Programming\test\test.js:16:xx)
at c:\Users\Domenic\Programming\test\test.js:19:xx
Agreed?
Wouldn't it be better if example 1 for async-generators could look like:
function test() {
var generator = Q.async(function () {
var ten = yield 10;
console.log(ten, 10);
var twenty = yield ten + 10;
console.log(twenty, 20);
var thirty = yield twenty + 10;
console.log(thirty, 30);
yield $return(thirty + 10);
});
Q.when(generator(), function (fourty) {
console.log(fourty, 40);
}, function (reason) {
console.log("error", reason);
});
}
To make this work you'd just need to include a function $return which returned an object with a known type and with the value attached. This could then be checked for in the async method instead of checking for the exception. Alternatively, if we must have the exception thrown, why not create a simple function which throws that exception, so as to hide some of the ugliness?
One of the most common questions I get when presenting on promises, and recommending Q, is "how big is this Q library you're telling me I need?" Putting something near the top of the readme (perhaps a tacky badge?) would probably be helpful for many.
I have an array of promisey functions, and I want to call them one after the other. What's a nice, concise way to do this?
The old README, under "Serial Join", had some nice exampes using Array.prototype.reduce
and Q.wait
. But Q.wait
is dead, not that I knew what it really did in the first place.
So far the best I have is
var array = [fooAsync, barAsync];
return array.reduce(function (soFar, thisFuncAsync) {
return soFar.then(thisFuncAsync);
}, Q.resolve());
But it feels weird having to pass in the empty Q.resolve
.
Q.isResolved(Q.defer())
seems to be broken. It yields true
where it should yield false
?
(npm ls installed
~ [email protected] active installed A library for promises (CommonJS/Promises/A,B,D)
)
Q should send messages to the console when promises are manipulated so that a monitor like a Causeway logger or Web Inspector view can be attached.
The corresponding console API is not defined. This is an idea to start the thinking process:
console.deferred(deferred);
console.resolved(promise);
console.fulfilled(promise);
console.rejected(promise);
It could be that my expectations are just wrong, but I was assuming that resolving or rejecting a promise that was already resolved or rejected will throw exception. In any case here are the tests
http://github.com/kriskowal/q/pull/1#L4R62
http://github.com/kriskowal/q/pull/1#L4R97
In case behavior is expected we can change tests accordingly.
Q.ncall
is really clever. I’m not 100% sure, but it might warrant a Function.prototype.qcall
, perhaps even an qfcall
(without a parameter for this
).
Before:
function expandUrl(shortUrl) {
var deferred = Q.defer();
return Q.ncall(request, null, {
method: "HEAD",
url: shortUrl,
followAllRedirects: true
}).get('request').get('href');
}
After:
function expandUrl(shortUrl) {
return request.qfcall({
method: "HEAD",
url: shortUrl,
followAllRedirects: true
}).get('request').get('href');
}
Thus: Instant q-ification of all Node.js functions. Instead of qcall
, one could also use the name nodecall
(still short, somewhat more descriptive).
.npmignore keeps some stuff out of npm that is not needed when q is installed in a project.
By excluding things it makes it easier/lighter to commit node_modules with q into a source repo.
Here is one that may work for q:
design
examples
lib
test
CHANGES.md
VERSIONS.md
q-spec.html
q-spec.js
q.min.js
q.min.js.gz
ref_send.md
You may use the smart syntax highlighting as described in http://github.github.com/github-flavored-markdown/.
IE9 (no idea about other versions) seems to only define window.console if the developer tools are open. Q calls console.log and thus won't (fully) work in IE9. Everything past the call to console.log presumably doesn't get executed, but it's hard to verify, given that this is a Heisenbug. (Opening the dev tools will cause Q to work fine.)
There's only one call to console.log in q.js, but I didn't understand its purpose well enough to just create a pull request. I would suggest wrapping console.log in an if (window.console !== undefined)
or simply removing the call.
FYI, a workaround is to include this line of script above the script tag pulling in q.js: if (window.console === undefined) window.console = { log: function () { } };
I did not see this in your library, so the following feature is critical:
Promise.pipe( function(result) {
....
return value || promise;
});
This feature supports promise chains, resolve() result transformations, resolve() rejections.
This is a HUGE missing feature. Please add to your library.
I'm not entirely sure if what I've run into is a bug in Q per se, or just weird behavior because I'm mis-using it, but in any case, I've constructed an example where both the resolved and rejected callbacks of a when
will get called. My understanding is that only one or the other should ever get called.
All you need to do to get the bad behavior is define a custom promise which always responds to when()
by returning a rejection, as opposed to calling the passed-in rejected
function. See below.
My best guess is that this isn't the recommended way to write a when()
though I would have also guessed that it should still work. BTW, I noticed that in the inner implementation, it doesn't count on rejected
being passed in, but at the level of my example here, is it actually safe to assume that it's a real function?
Here's the code:
var Q = require("q");
function makePromiseCore() {
function post(name, args) {
return "hello";
}
function when(rejected) {
return Q.reject(new Error("permanently unresolved"));
}
return {
post: post,
when: when
};
}
function onResolved(value) {
console.log("Resolved to:", value);
}
function onRejected(value) {
console.log("Rejected as:", value);
}
var promise = Q.makePromise(makePromiseCore());
promise.when(onResolved, onRejected);
And here's a transcript of running it:
$ node ./weirdwhen.js
Rejected as: [Error: permanently unresolved]
Resolved to: undefined
Thanks for your consideration. I'm generally quite enthused with this module!
global.setImmediate
is a proposed-for-standardization version of Q.nextTick
.
It does not seem to be winning the battle for the hearts and minds of spec editors (MDN says "is not expected to become standard"; negative comments from Hixie in a related bug). But, it does seem to be winning the hearts and minds of developers (blog post from Nicholas Zakas; dependencies from a reasonably-popular Knockout.js plugin; even a (closed) bug to use it in underscore.js). So it might get somewhere in the end, and Q's support could help push things in that direction.
Currently the only way to get it is through manually shimming it; the only browser to have it natively is IE9, and there it's hidden behind a prefix. So if we said var nextTick = global.setImmediate || (existing code)
, this would only work for people who have included a shim.
Still, this seems like a win. For shim users, it gives faster promises in non-MessageChannel
-supporting browsers. It would also solve #44, by allowing users in the add-on SDK environment to do a quick shim like global.setImmediate = require("event-queue").enqueue
.
What do you think?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.