Code Monkey home page Code Monkey logo

p-map's Introduction

p-map

Map over promises concurrently

Useful when you need to run promise-returning & async functions multiple times with different inputs concurrently.

This is different from Promise.all() in that you can control the concurrency and also decide whether or not to stop iterating when there's an error.

Install

npm install p-map

Usage

import pMap from 'p-map';
import got from 'got';

const sites = [
	getWebsiteFromUsername('sindresorhus'), //=> Promise
	'https://avajs.dev',
	'https://github.com'
];

const mapper = async site => {
	const {requestUrl} = await got.head(site);
	return requestUrl;
};

const result = await pMap(sites, mapper, {concurrency: 2});

console.log(result);
//=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']

API

pMap(input, mapper, options?)

Returns a Promise that is fulfilled when all promises in input and ones returned from mapper are fulfilled, or rejects if any of the promises reject. The fulfilled value is an Array of the fulfilled values returned from mapper in input order.

pMapIterable(input, mapper, options?)

Returns an async iterable that streams each return value from mapper in order.

import {pMapIterable} from 'p-map';

// Multiple posts are fetched concurrently, with limited concurrency and backpressure
for await (const post of pMapIterable(postIds, getPostMetadata, {concurrency: 8})) {
	console.log(post);
};

input

Type: AsyncIterable<Promise<unknown> | unknown> | Iterable<Promise<unknown> | unknown>

Synchronous or asynchronous iterable that is iterated over concurrently, calling the mapper function for each element. Each iterated item is await'd before the mapper is invoked so the iterable may return a Promise that resolves to an item.

Asynchronous iterables (different from synchronous iterables that return Promise that resolves to an item) can be used when the next item may not be ready without waiting for an asynchronous process to complete and/or the end of the iterable may be reached after the asynchronous process completes. For example, reading from a remote queue when the queue has reached empty, or reading lines from a stream.

mapper(element, index)

Type: Function

Expected to return a Promise or value.

options

Type: object

concurrency

Type: number (Integer)
Default: Infinity
Minimum: 1

Number of concurrently pending promises returned by mapper.

backpressure

Only for pMapIterable

Type: number (Integer)
Default: options.concurrency
Minimum: options.concurrency

Maximum number of promises returned by mapper that have resolved but not yet collected by the consumer of the async iterable. Calls to mapper will be limited so that there is never too much backpressure.

Useful whenever you are consuming the iterable slower than what the mapper function can produce concurrently. For example, to avoid making an overwhelming number of HTTP requests if you are saving each of the results to a database.

stopOnError

Only for pMap

Type: boolean
Default: true

When true, the first mapper rejection will be rejected back to the consumer.

When false, instead of stopping when a promise rejects, it will wait for all the promises to settle and then reject with an AggregateError containing all the errors from the rejected promises.

Caveat: When true, any already-started async mappers will continue to run until they resolve or reject. In the case of infinite concurrency with sync iterables, all mappers are invoked on startup and will continue after the first rejection. Issue #51 can be implemented for abort control.

signal

Only for pMap

Type: AbortSignal

You can abort the promises using AbortController.

import pMap from 'p-map';
import delay from 'delay';

const abortController = new AbortController();

setTimeout(() => {
	abortController.abort();
}, 500);

const mapper = async value => value;

await pMap([delay(1000), delay(1000)], mapper, {signal: abortController.signal});
// Throws AbortError (DOMException) after 500 ms.

pMapSkip

Return this value from a mapper function to skip including the value in the returned array.

import pMap, {pMapSkip} from 'p-map';
import got from 'got';

const sites = [
	getWebsiteFromUsername('sindresorhus'), //=> Promise
	'https://avajs.dev',
	'https://example.invalid',
	'https://github.com'
];

const mapper = async site => {
	try {
		const {requestUrl} = await got.head(site);
		return requestUrl;
	} catch {
		return pMapSkip;
	}
};

const result = await pMap(sites, mapper, {concurrency: 2});

console.log(result);
//=> ['https://sindresorhus.com/', 'https://avajs.dev/', 'https://github.com/']

Related

  • p-all - Run promise-returning & async functions concurrently with optional limited concurrency
  • p-filter - Filter promises concurrently
  • p-times - Run promise-returning & async functions a specific number of times concurrently
  • p-props - Like Promise.all() but for Map and Object
  • p-map-series - Map over promises serially
  • More…

p-map's People

Contributors

bendingbender avatar chrisblossom avatar coreyfarrell avatar ferrinweb avatar furudean avatar ghiscoding avatar huntharo avatar jopemachine avatar kevnz avatar noamokman avatar papb avatar parro-it avatar richienb avatar samverschueren avatar sindresorhus avatar yaodingyd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

p-map's Issues

UglifyJsPlugin: Invalid assignment

Hello,

Here is my UglifyJsPlugin config;

new webpack.optimize.UglifyJsPlugin({
          compress: {
            warnings: false,
            screw_ie8: true,
            conditionals: true,
            unused: true,
            comparisons: true,
            sequences: true,
            dead_code: true,
            evaluate: true,
            if_return: true,
            join_vars: true,
            drop_console: true,
          },
          output: { comments: false },
          sourceMap: true
        })

Here's the error I get;

ERROR in js/vendor_b535d98.js from UglifyJs
Invalid assignment [./node_modules/p-map/index.js:2,0][js/vendor_b535d98.js:1709,42]

ERROR in js/main_b535d98.js from UglifyJs
Unexpected token: operator (>) [./src/util/js/api.js:7,8][js/main_b535d98.js:26,12]

Even If I completely remove the options, (new UglifyJS()) minification still errors out.

The line it yells at;

module.exports = (iterable, mapper, opts) => new Promise((resolve, reject) => {

which seems perfectly OK to me.

Do you have any solution besides switching my uglifyJS method? That is the only idea I'm left with.

Don't convert input to an array

const input = Array.from(iterable);

The iterable should be used directly instead of converting to an array. It would have the benefit of better supporting generated sequences.

A pull request would be wonderful 🙌🌟

SyntaxError: Cannot use import statement outside a module

After upgrading the module version from v4 -> v5 we start seeing an error:

 Details:

    /node_modules/p-map/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import AggregateError from 'aggregate-error';
                                                                                             ^^^^^^

    SyntaxError: Cannot use import statement outside a module

    > 11 | import pMap from 'p-map';
         | ^

Please let me know if you need more info.

p-map v3.0.0 does not work with react-native

After upgrade the following error shows:

Loading dependency graph, done.
error: bundling failed: Error: Unable to resolve module `os` from `[..]/node_modules/clean-stack/index.js`: Module `os` does not exist in the Haste module map

I am using android with react-native v0.59.10

Decimal values for concurrency

The following loop controls the number of pending promises returned by mapper.

for (let i = 0; i < concurrency; i++) { next(); if (isIterableDone) { break; } }.

However, if concurrency has a decimal value (for instance, if concurrency = 2.5), there will be 3 pending promises because the loop allows one more iteration to happen (the case in which i=2).

Is this a bug or it is actually intentional? Shouldn't we avoid such cases? If so, the bug could potentially be fixed by adding a condition when validating the value of concurrency.

p-flat-map

I encountered the need for p-flat-map. Here's what I came up with:

const pFlatMap = async <Element, NewElements>(
  input: Iterable<Element>,
  mapper: pMap.Mapper<Element, NewElements>,
  options?: pMap.Options
): Promise<FlatArray<NewElements[], 1>[]> => {
  const mapped: NewElements[] = await pMap(input, mapper, options)
  return mapped.flat()
}

Usage example:

const products = await pFlatMap(categories, listProductsForCategory, { concurrency: 50 })

Would it be possible to add this to the collection?

Typescript typings

I'm having issues with non-bundled typings from @types/p-map, it'll be easier if they are bundled and import * as pMap from 'p-map' just works.

I've noticed in e.g Ky and p-throttle typings are now bundled with the package, would be nice to have it here too.

Coverage gap

I used Istanbul to measure coverage of the test suite and I believe that I found a minor coverage gap.

It looks like the condition of the following if statement never holds.

if (typeof mapper !== 'function') {
  throw new TypeError('Mapper function is required');
}

It is a corner case and probably unlikely to happen, but it may be worth including a test just to make sure this property will hold in future. I include a suggestion of test below, which passes when I run locally.

test('invalid mapper', async t => {
  await t.throwsAsync(pMap([], "invalid mapper", {concurrency: 2}), TypeError);
});

Support aborting the mapping

e.g. a few seconds into waiting for the promise to finish, we could increase concurrency due to CPU limit being lowered below 20%, to a concurrency of 5x or something. Basically dynamic concurrency

FR: introduce `p` function for concurrent promise execution with condition

I'm not sure if this is the right place to submit an idea, but it would be interesting to have a function p that allows executing a specified number of promises concurrently while a condition is true.

In my specific case, I have a list with 200 items and need to check if at least 5 of them have a certain "quality". Since it is a time-consuming process and the outcome is quite random, I activate 10 concurrent executions and keep performing an items.shift() operation to test each item.

Once I reach 5 successful elements, I pause the processing. However, when the number of elements drops below 5 again, I need to resume searching for new elements. In my particular case, it's not a problem if I find more than 5 elements, as some of the concurrent executions may still be pending even after pausing.

Here's a rough outline of the idea:

const p = pFunctionHere({ 
  concurrency: 10, 
  afterPausedInterval: 100, // When the condition is reached the first time (returning `false`), then every 100ms it will be executed again to see if it is necessary to restart the concurrencies.
});

const tester = async () => {
  // Get an item from the list.
  const item = items.shift(); 

  if (await isValid(item)) { // Time-consuming process.
    const testItem = addItem(item); // addedItems.push(...)
    testItem.test(); // Test the item every minute.
  }
}

const condition = () => {
  return items.length > 0 && addedItems.length < 5;
}

p.run(tester, condition);

This feature would allow executing tester function concurrently up to the specified concurrency limit (10 in this case) while the condition condition is true. Once the condition is no longer met, the execution would pause until the condition becomes true again.

It would be great to have this functionality as it provides a convenient way to handle concurrent promise execution with a condition.

Introducing `throwOnError` option for comprehensive promise chain results

I think this package is missing an important functionality, and that is to see the results of resolved promises when one of the promises from the promise chain gets rejected. When stopOnError is set to false if some of the promises are rejected, I am not able to get fulfilled results, instead, the error is thrown.

It would be good to have similar behavior like Promise.allSettled to see the results of the promises and their status. EG if resolved, we can see the resolved result and if rejected we can see the error.

Maybe we can have an additional option, throwOnError which will be true by default to not break the functionality, but have the ability to have the functionality explained above.

I am happy to open a PR if you would like to include this functionality in your package.

Must use import to load ES Module

I bump my service which are using p-map for testing from version 4.0.0 to 5.0.0 and now I got the following issue during my test.

node version v14.16.0

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: .../node_modules/p-map/index.js require() of ES modules is not supported. require() of .../node_modules/p-map/index.js from ..../tests/contracts/step_definitions/test.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from .../node_modules/p-map/package.json.

is is a breaking change not documented? if yes how I can fix then

note I use pMap using import

import pMap from 'p-map';

Compare with Promise.all()

I think pMap() has the same behavior with the built-in Promise.all(). Am I right?
And further more, what is pMap()'s advantage, in other words, why or when we should use pMap() instead of the built-in Promise.all()?

Can anyone answer my question?

Forgive my poor English...

Allow leaving an empty value

For example:

await pMap(["example.com", "notawebsite.invalid", "google.com"], async url => {
	try {
		return await got(url)
	} catch {
		return pMap.hole()
	}
})
//=> ["<example.com contents>", "<google.com contents>"]

Issue when trying to compile a react project using p-map

Hi, I used p-map on my react application and when I'm trying to build production package, it fails with following output:

> react-scripts build

Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file:

 	./node_modules/p-map/index.js:2

Read more here: http://bit.ly/2tRViJ9

Suggestion being, publishing package in npm with pre-compiled version included in the package. Does it makes sense? Can you do it?

Allow breaking from iterator

I wish I could stop the iteration early by returning something like pMap.stop (a Symbol) from the iterator.

This is basically the same request as sindresorhus/p-each-series#3

For now, I have to throw an error on purpose just to break it. Thankfully, I don't need the return value of p-map anyway.

But with this feature, the parts of the array that weren't computed yet could be set to undefined, or pMap.uncomputed (another Symbol), or even be specified by a valueForUncomputedEarlyStop option.

Can I do a PR?

A way to set recommended/reasonable value for concurrency

Do you have a module that calculates and exports a reasonable default value for concurrency? For example what is done in sindresorhus/got#393. I'm planning to use p-map in some parts of nyc that can be async so I want to set a reasonable concurrency limit. I'd like to avoid calculating os.cpus().length multiple times and avoid duplicating the CI limiting logic.

Consider rejecting only on rejected Promises.

According to the documentation, pMap returns

a Promise that is fulfilled when all promises in input and ones returned from mapper are fulfilled, or rejects if any of the promises reject.

But strictly speaking, it's

a Promise that is fulfilled when all promises in input and ones returned from mapper are fulfilled, or rejects if any of the promises reject, or mapper or options.concurrency are invalid, or mapper throws.

It's a subtle difference, especially if you're awaiting pMap or passing an async function as mapper.

webpack build failed

ERROR in ../node_modules/p-map/node_modules/aggregate-error/index.js 7:1
Module parse failed: Unexpected character '#' (7:1)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| export default class AggregateError extends Error {
> 	#errors;

Undefined items added to resulting mapped collection

Random undefined items are added to my mapped array with version 1.1.0. I don't have the same issue with version 1.0.0 or with bluebird. I've been able to consistently reproduce the issue with the following test. The same test works with concurrency 1 or concurrency >= myInput.length.

test('async with concurrency: 2', async t => {
	const myInput = [100, 200, 10, 36, 13, 45];
	const myMapper = value => {
		return new Promise(resolve => {
			setTimeout(() => resolve(value), value);
		});
	};

	t.deepEqual(await m(myInput, myMapper, {concurrency: 2}), myInput);
});

It is not obvious to see the extra undefined items with the ava output (I've never used ava before) but my mocha/chai version of the test is showing this output:

AssertionError: expected [ 100, 200, 10, , 36, , 13, , 45 ] to deeply equal [ 100, 200, 10, 36, 13, 45 ]
      + expected - actual

       [
         100
         200
         10
      -  [undefined]
         36
      -  [undefined]
         13
      -  [undefined]
         45
       ]

stopOnError doesn't work as expected with high concurrency values

I've an array of millions of elements to save in a database and I want to run those queries in parallel with a concurrency of 1000. I also would like to stop the entire execution if one of those queries fails. However, when is set concurrency: 1000 together with stopOnError: true, the process stops only when all the 1000 promises are resolved (even though the first one fails)

I cannot share my code but it might be tested using the sample from the readme in this way:

import pMap from 'p-map';
import got from 'got';

const sites = [
	'invalidurl',
	...new Array(10000).map(()=>'https://github.com'),
];

const mapper = async site => {
	const {requestUrl} = await got.head(site);
	return requestUrl;
};

const result = await pMap(sites, mapper, {concurrency: 1000, stopOnError: true});

console.log(result);

Invalid url should throw an error and stop the execution of the other in pending urls

type inference in vscode with pure javascript doesn't work

Hey,

i saw with #13 typescript bindings were added. I'm also a using this lib quite often + work with vscode, but it seems the type inference does not work with pure javascript. Here's an example:

const test = () => {
  const myList = [1,2,3,4];
  return pmap(myList, (item) => item * 3)
}

For the functions return value i just get any (not even Promise).

Doing similar with e.g. _.map works, so i assume somehow we can get this running with js. I haven't written d.ts files before, so not sure what's actually causing this?

Thanks for this great lib btw.

Should be able to get resolved values when stopOnError=false

Should be able to get both resolved values, and aggregate error, like in p-settle. I'm looking for the combination of p-settle and p-map which seems not to exist...

With p-settle (even when supplying function) it's called immediately. In my case this starts all the requests at once.

With p-map it throttles the requests according to concurrency but there is no way to get the resolved results if any request fails.

.finally does not work for me with pMap

hi Sindre, guys,

Whenever I append .finally I get this error message:
TypeError: pMap(...).catch(...).finally is not a function

For example, here I try to write bunch of files asynchronously:

const fs = require("fs-extra");
const pMap = require("p-map");
// ...
pMap(filesToWrite, oneToDoObj => {
    fs
      .outputFile(
        oneToDoObj.name,
        resolveVars(oneToDoObj.contents)
      )
      .then(log(chalk.green(logSymbols.success, oneToDoObj.name)));
  })
    .then(() => {
      step2();
    })
    .catch(err => {
      log(`${chalk.red(logSymbols.error, `error writing file:\n${err}`)}`);
      step2();
    })
    .finally(() => {
      console.log("finally");
    });

The code above does work without the last .finally step.
It's as if .finally was not allowed.
By the way, me calling step2() and not returning promise above is not an issue, I tried returning Promise.resolve()'d function, same thing - works without .finally, doesn't with it.

Did you ever try .finally on pMap and did it work for you?

Thank you.

`Must use import to load ES Module` (with typescript)

Hello,

How to use this library with typescript?
I'm getting this error:

Must use import to load ES Module: /home/omar/Desktop/node_modules/p-map/index.js\n' +
    'require() of ES modules is not supported.\n' +
    'require() of /home/omar/Desktop/node_modules/p-map/index.js from /home/omar/Desktop/src/resolvers/views.ts is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.\n' +
    'Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/omar/Desktop/node_modules/p-map/package.json.

Here's my tsconfig:

{
    "compilerOptions": {
        "target": "ES2018",
        "module": "CommonJS",
        "lib": [
            "es2020",
            "esnext.asynciterable"
        ],
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "esModuleInterop": true,
        "outDir": "dist",
        "baseUrl": "src",
        "sourceMap": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "moduleResolution": "node",
        "removeComments": true,
    },
    "include": [
        "src/**/*.ts",
        "prisma/**/*.ts",
    ],
    "exclude": [
        "node_modules/**/*",
        "_warmup/**/*",
        ".vscode/**/*",
        ".husky/**/*",
        "dist/**/*"
    ],
}

Browser Compatibility with `^5.0.0`

After upgrading to ^5.0.0, vite got an error:

browser-external:os:3 Uncaught Error: Module "os" has been externalized for browser compatibility and cannot be accessed in client code.
    at Object.get (browser-external:os:3:11)
    at index.js:6:27

After some digging, this is related to aggregate-error ^4.0.0's dep clean-stack ^4.0.0

import os from 'os' (index.js#L1)

I wonder could homedir be implemented in a browser-friendly way?

I don't know which repo is the most suitable place to open this issue, please transfer to the right place if needed.

Thank you!

Question about some tests

Hi all, and thank you very much for your effort on delivering such great tools!

I was reading the tests, in particular:

test('main', async t => {
	const end = timeSpan();
	t.deepEqual(await pMap(sharedInput, mapper), [10, 20, 30]);
	t.true(inRange(end(), {start: 290, end: 430}));
});

test('concurrency: 1', async t => {
	const end = timeSpan();
	t.deepEqual(await pMap(sharedInput, mapper, {concurrency: 1}), [10, 20, 30]);
	t.true(inRange(end(), {start: 590, end: 760}));
});

and I would like to ask how the numbers for start and stop came out? For example, for the first test I would expect the start value to be at least 300. Are those numbers dependent on the machine workload at the time the tests are running?

Stack trace is lost from the point the code uses p-map

Both, console.trace and throw new Error don't show the stack-trace beyond the point p-map got called. In other words, the functions that called before pMap, disappear from the stack trace.
As a comparison, the p-map-series doesn't suffer from this issue. It does keep the stack-trace.

See the example below, if you run a function that runs the native Promise.all, the stack trace shows the function name - runPromiseNative. Same if you run the function runPromisePmapSeries. However, try to run runPromisePmap, and you'll see how the stack trace truncated.

I tried node v12.x and v14.x.

const pMap = require('p-map');

const pMapSeries = require('p-map-series');

async function promiseFn() {
  throw new Error('stop')
}

async function runPromiseNative() {
  await Promise.all([promiseFn()]).then(() => { console.log('completed') }).catch((err) => console.error(err));
}

async function runPromisePmap() {
  await pMap([promiseFn], fn => fn()).then(() => { console.log('completed') }).catch((err) => console.error(err));
}

async function runPromisePmapSeries() {
  await pMapSeries([promiseFn], fn => fn()).then(() => { console.log('completed') }).catch((err) => console.error(err));
}

// runPromiseNative();

runPromisePmap();

// runPromisePmapSeries();

Results when running runPromisePmap :

Error: stop
    at promiseFn (/Users/davidfirst/teambit/bit/pmap.js:6:9)
    at /Users/davidfirst/teambit/bit/pmap.js:14:33
    at /Users/davidfirst/teambit/bit/node_modules/p-map/index.js:57:28

Results when running runPromiseNative.

Error: stop
    at promiseFn (/Users/davidfirst/teambit/bit/pmap.js:6:9)
    at runPromiseNative (/Users/davidfirst/teambit/bit/pmap.js:10:22)
    at Object.<anonymous> (/Users/davidfirst/teambit/bit/pmap.js:21:1)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

Alias for `Infinity`

I happen to configure the concurrency option through JSON, but JSON cannot encode a Infinity value. Would you agree to taking 0 or -1 as an alias for Infinity?

Support esm and commonjs exports in package.json

Is it possible to provide exports in both esm and cjs formats. For example:

{
    "exports": {
        ".": {
             "node": {
                  "import": "./index.mjs",
                  "require": "./index.cjs"
              },
              "default": "./index.mjs"
        }
    }
}

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.