Coder Social home page Coder Social logo

englercj / resource-loader Goto Github PK

View Code? Open in Web Editor NEW
420.0 11.0 79.0 1.05 MB

A middleware-style generic resource loader built with web games in mind.

Home Page: http://englercj.github.io/resource-loader/

License: MIT License

JavaScript 56.29% TypeScript 43.71%
resource-loader javascript xhr xdr ajax

resource-loader's Introduction

Resource Loader Build Status

A generic resource loader, made with web games in mind.

Philosophy

This library was built to make it easier to load and prepare data asynchronously. The goal was mainly to unify the many different APIs browsers expose for loading data and smooth the differences between versions and vendors.

It is not a goal of this library to be a resource caching and management system, just a loader. This library is for the actual mechanism of loading data. All caching, resource management, knowing what is loaded and what isn't, deciding what to load, etc, should all exist as logic outside of this library.

As a more concrete statement, your project should have a Resource Manager that stores resources and manages data lifetime. When it decides something needs to be loaded from a remote source, only then does it create a loader and load them.

Usage

// ctor
import { Loader } from 'resource-loader';

const loader = new Loader();

loader
    // Chainable `add` to enqueue a resource
    .add(url)

    // Chainable `use` to add a middleware that runs for each resource, *after* loading that resource.
    // This is useful to implement custom parsing modules (like spritesheet parsers).
    .use((resource, next) =>
    {
        // Be sure to call next() when you have completed your middleware work.
        next();
    })

    // The `load` method loads the queue of resources, and calls the passed in callback called once all
    // resources have loaded.
    .load((loader, resources) => {
        // resources is an object where the key is the name of the resource loaded and the value is the resource object.
        // They have a couple default properties:
        // - `url`: The URL that the resource was loaded from
        // - `error`: The error that happened when trying to load (if any)
        // - `data`: The raw data that was loaded
        // also may contain other properties based on the middleware that runs.
    });

// Throughout the process multiple signals can be dispatched.
loader.onStart.add(() => {}); // Called when a resource starts loading.
loader.onError.add(() => {}); // Called when a resource fails to load.
loader.onLoad.add(() => {}); // Called when a resource successfully loads.
loader.onProgress.add(() => {}); // Called when a resource finishes loading (success or fail).
loader.onComplete.add(() => {}); // Called when all resources have finished loading.

Building

You will need to have node setup on your machine.

Then you can install dependencies and build:

npm i && npm run build

That will output the built distributables to ./dist.

Supported Browsers

  • IE 9+
  • FF 13+
  • Chrome 20+
  • Safari 6+
  • Opera 12.1+

Upgrading to v4

  • Before middleware has been removed, so no more pre function.
    • If you used pre middleware for url parsing, use the new urlResolver property instead.
  • crossOrigin must now be a string if specified.
  • Resource.LOAD_TYPE enum replaced with Load Strategies.
    • For example, loadType: Resource.LOAD_TYPE.IMAGE is now strategy: Loader.ImageLoadStrategy.
  • Resource.XHR_RESPONSE_TYPE enum replaced with XhrLoadStrategy.ResponseType.
    • For example, xhrType: Resource.XHR_RESPONSE_TYPE.DOCUMENT is now xhrType: Loader.XhrLoadStrategy.ResponseType.Document.
  • Overloads for the add function have been simplified.
    • The removed overloads were not widely used. See the docs for what is now valid.

resource-loader's People

Contributors

andrejefimov avatar bash avatar bigtimebuddy avatar cursedcoder avatar davearel avatar englercj avatar exkazuu avatar ivanpopelyshev avatar jancassio avatar krzysztof-o avatar ladrower avatar lekzd avatar marekventur avatar naranjamecanica avatar rblstr avatar richard-livingston avatar rtibbles avatar stbaer avatar thammin avatar vitalije avatar vlucendo 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

resource-loader's Issues

Need a way for middleware to add to the queue

Right now if I have a parser (say of a manifest) that then loads many other files, then progress events for the loader are pretty much borked. Needs to be a way to know how many files will be loaded for proper progress events, otherwise the progress may decrease at points (which is undesired behavior).

Other loaders use a type-based "add" system that allows users to add a resource of a certain type which means we "know" how many resources will eventually need to be loaded.

Maybe have a different type of .add specifically for manifests (.addManifest) that makes that resource not be part of the progress. All manifests are first loaded, parsed (which can add resources to the queue), then the queue is loaded and progress events work as expected.

dist folder content crashes text editors

After running gulp and building out dist folder the resultant .js and .min.js crash my text editors (both sublime and atom) upon attempting to view.
This happens on every attempt of cloning repo.
This may be an issue with my setup in some way, sorry for the non-code specific issue. Thought I should mention in case others are experiencing.

Retry when loader emits error

Hi - i can't seem to find a way to retry when a resource fails to load.
I build an app with pixi and sometimes some of the assets does not load.

loader.on('error', function (loadErr , loader, resource){
    resource .load() // was hoping for something like this   
})

I can't add the same resource again, causes a Loader.js:238 Uncaught Error: Resource with name "asda" already exists.

Is there a recommend way to try a reload?

Any help would be appriciated,

I am using version 2.0

/Dennis

Add real loaded percentage

I forked the project and added few stuffs to handle a real percentage progression based on the total weight of files.

It doesnt handle request error at the moment, and slightly made few changes :

the original 'progress' event become 'file' event and is fired everytime a file is loaded

'progress' event is fired everytime a new chunk of data has been loaded, you can access the progression percentage with progresstotal

I did it very fast for my own purpose.

If you guys want to give a hand :

[(https://github.com/Samsy/resource-loader)]

A test unit related to event progress even middleware add more resources, fail "sometimes"

Hi sir @englercj,

I'm playing with the resolution test proof of my pull request I sent to you and I found something strange.

Checkout the log below:

not ok 35 Firefox 39.0 - Loader events progress should be 100% on complete, even when a middleware adds more resources
    ---
        message: >
            AssertionError: expected { Object (baseUrl, progress, ...) } to have a property 'progress' of 100, but got 91.81818181818183 (:0)
        stack: >
            process.on/global.onerror@http://localhost:7357/testem/mocha.js:5736:10

        Log: >
    ...

I'm not able to guess but I'll investigate. Let me know if you have any clue.

Thanks,
Jan

npm v1.6.7 does not include /src

Since package.json main is src/index.js, packages that depend on resource-loader aren't working (pixi.js for me).

1.6.6 works fine. I noticed you added the package.json files field. I think using non-relative paths should fix this.

how to work with howlerjs ?

I think there is a way for third party loader to work with resource-loader , but I don't know how to do it , maybe could someone tell me how to make howlerjs work with resource loader as a start point ?

Feature request : compressed texture

Hello !

As you may have see on PIXI github, I'm working on compressed textures for WebGL. We are getting some very nice results in our own engine but dealing wih PIXI and RessourceLoader is a bit too much for me alone.

The thing is PIXI uses an image object for textures. With compressed textures, we need an Int32Array to store the file because an Image() object will not load a .dds or .pvr file.

Could you handle a new type of file (binary file) to be able to load DXT, PVR, ETC and ASTC format please ?

It would require some extra check, fortunatly someone did the homework for us here : https://github.com/toji/texture-tester/blob/master/js/webgl-texture-util.js

As a reminder, compressed texture saves as least 4 times the size of an uncompressed texture in the GPU memory and are faster to bind. This is huge !

Regards.

about progress percent value

sometimes the progress percent value is very long , I think we could use something like decimalCount param to make the percent decimal more controllable .

Adding an array

Hey there! I got a simple question. I am moving from pixi.js v2 to v3 and I noticed the change to the your resource loaded. So I was wondering if it was possible to add an array to the loader similar to the version 2 api and if it the name param is required. Currently I am doing the following

      loader = new PIXI.loaders.Loader()
      for url in urls
        loader.add url,url
      loader.once('complete',callback)
      loader.load()

but I would prefer to do something like below

      loader = new PIXI.loaders.Loader()
      loader.add urls
      loader.once('complete',callback)
      loader.load()

Thanks

Stupid side question, what is the purpose of the name parameter?

IE11 Issue with sending cookies in request headers

I am using pixijs version 3.0.2 and facing an unusual error in IE 11. The PNG spritesheets are not loading as pixi loader fails to pass session cookies while making the request to the server for the image (PNG) files. The server denies the request thinking that its an unauthorized access without the session cookies in the request headers. I receive a 403 Forbidden response from the server. Below is the request header sent to the server by pixi:

Key Value
Response HTTP/1.1 403 Forbidden
Server AkamaiGHost
Mime-Version 1.0
Content-Type text/html
Content-Length 176
Expires Mon, 05 Oct 2015 12:59:03 GMT
Cache-Control max-age=0, no-cache, no-store
Pragma no-cache
Date Mon, 05 Oct 2015 12:59:03 GMT
Connection keep-alive

I also have a normal GIF file used in the IMG src tag; in the same package uploaded to the CMS which loads without errors. Below is the request header sent to the server for this:

Key Value
Request GET http://media2-qa.cdiapps.com/repository/protected_content/COMPOUND/50001336/57/16/deploy/media/images/loader.gif HTTP/1.1
Accept image/png, image/svg+xml, image/;q=0.8, */;q=0.5
Referer http://media2-qa.cdiapps.com/repository/protected_content/COMPOUND/50001336/57/16/deploy/index.html?reviewFlag=false&backUrl=%2Fem4s%2Fgames&context=%7B%22classId%22%3A%22%22%2C+%22gameId%22%3A%22464SB1Q1LNPFDO53FX3RERQTSQ%22%2C+%22bookId%22%3A%22WKFLPQPK563VPDFY6V1FMBXSYE%22%7D&pingUrl=%2Fconnected%2Fkeepalive.form&students=%5B%7B%22studentid%22%3A%22EHC4PHMZYF5CVZ3HT67O1GZSPY%22%2C%22name%22%3A%22Vincent%22%7D%2C%7B%22studentid%22%3A%22student123%22%2C%22name%22%3A%22Brad%22%7D%5D&timeoutInMin=130&connectEDBaseUrl=http%3A%2F%2Fconnected-qa.cdiapps.com%2F&saveServiceJS=%2Fem4t%2FsaveGameEvent.js
Accept-Language en-US
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding gzip, deflate
Proxy-Connection Keep-Alive
DNT 1
Host media2-qa.cdiapps.com
Pragma no-cache
Cookie token=exp=1444062022~acl=/repository/protected_content/COMPOUND/50001336/57/16/*~hmac=29a424ed54dbf424830a8ece0a95c4dcec23e02b9f4593ec1c9f814f8dea0ee9; PORTALLB=3467057836.55303.0000; JSESSIONID=DFEAA6998C797B5C983CA32D8247083A; _ga=GA1.2.570359160.1443448507

'.' in query string breaks extension matching

http://example.com/image.png?tag=0.12345 will cause the loader to believe the extension is 12345 not png and it will fail to load the image.

Don't know if this deliberate, but caused a problem for me when I was trying to use Math.random() as an update flag.

Forcing XML and JSON to load in plain text.

Hi,
If we want to use custom parsing for XML and JSON we are now unable to do so...
For example, use the Haxe XML parser or more permissive JSON parsing methods...

I can imagine a text option type when calling ResourceLoader.add():

.add("xml", "test.xml", {text:true});

It could be then handled in Resource._xhrOnLoad()

if (this.xhrType === Resource.XHR_RESPONSE_TYPE.TEXT || options.text===true) { ...

'complete' triggered before 'error'

Hello,

First of all, thanks for the awesome loader class. I use the loader for multiple file loads in a project and it works great. I just wondering why the 'complete' is first called before the 'error' when the last item of queue fails to load. What's the exact reason for that? Wouldn't it be better if the 'complete' is fired after all items are handled?

Cheers,
Pieter

Resource loader not able to load files after reset in some cases

The resource loader is no longer able to load any files if it is reset while there are more than its concurrency limit of files in its queue.

Minimal test case for this issue (I compiled this script with browserify and loaded it inside an HTML file; test1.png to test4.png are just arbitrary files):

var Loader = require('resource-loader');
var concurrency = 2;
var loader = new Loader(null, concurrency);

loader.add('test1.png').add('test2.png').add('test3.png').load();

setTimeout(function() {
  loader.reset();
  loader.add('test4.png', finishedLoading).load();
}, 0);

function finishedLoading() {
  console.log('Finished Loading');
}

This script loads three files then immediately resets the loader and tries to load a fourth file. When setting concurrency to 4 or higher, the last file is loaded correctly and the message 'Finished Loading' appears in the console.
If concurrency is 3 or less, the file is not loaded and the message does not appear.

I tried to debug the problem myself but could not pinpoint the exact issue. If you remove the section in Loader.reset starting with the comment "abort all resource loads" , the problem does no longer occur, but of course this is probably not an ideal solution.

Reduce File Size

Async queue and node-url contribute heavily to file size. Try to replace those deps with something more trim.

More details: Fae/fae#22

Extension is being improperly detected

We have image URLS like http://domain.com/images/abc.png?123456 where 123456 is an automatically generated timestamp used for cache invalidation. Resource type for such images is being improperly detected when loading which causes issues in a framework (pixi.js) that use your project for resource loading.

Is that possible to exclude everything after ? from extension?

Scope

I'm not seeing where I set the scope of the callback function. How can this be achieved.
Thank you!

Loader broken

Password protected servers

Hi there !
I'm actually using this loader everywhere now that it's "out" of the pixi core, great work here :)

This one is not really a big issue, but maybe it deserves a mention in the readme, or just your opinion on the subjet.

On IE11, loading images from our staging server (which is now protected by a password since we are not launched yet) fails every time, and returns a 401 error. The quickest way I found was to force XHR loading (instead of detected img loading) via the options.

Is there a better/automatic way? Anyway I thought someone using resource-loader might want to know that. Cheers!

Concurrency limit seems to create a bug with BitmapFont load (pixi)

Hello,

First, please note that there is one diff between the master code and the code in the following test case :

  • At line 21872 of pixi.js, we added temp fix for XML parsing

In this test case, the loading never end and stop after 10 files : http://www.celsius-heroes.com/game3/bugLoader.html

In this test case, we modified the concurrency limit to "100" and the loading is sucessfull :
http://www.celsius-heroes.com/game3/bugLoader2.html

I do believe that it may be linked to adding more ressources to the queue while it is already in a loading state.

Please check the HTML for the source code.

Regards.

a bug in Loader.prototype._handleBaseUrl

Hello I was just studying Loader code and found a bug that is unlikely to show any effect in most practical cases.Nevertheless, I believe it should be fixed.

Loader.prototype._handleBaseUrl = function (url) {
    var parsedUrl = urlParser.parse(url);

    // absolute url, just use it as is.
    if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) {
        return url;
    }

    // if baseUrl doesn't end in slash and url doesn't start with slash, then add a slash inbetween
    if (
        this.baseUrl.length &&
        this.baseUrl.lastIndexOf('/') !== this.baseUrl.length - 1 &&
        //HERE INSTEAD
        //  url.lastIndexOf('/') !== url.length - 1
        // SHOULD BE
        url.charAt(0) !== '/'
        // so that this part  of code works like described in the comment above the 'if' statement
    ) {
        return this.baseUrl + '/' + url;
    }
    else {
        return this.baseUrl + url;
    }
};

In cases where baseUrl doesn't end with a slash, and url doesn't begin with a slash, but ends with a slash the original method would return wrong url.
console.log(new Loader('http://example.org')._handleBaseUrl('wrong/'));
would produce the following result:

http://example.orgwrong/
HTH.

memory.js-style "before" middleware does not appear to work without next() call

There's an example for implementation of "caching" before middleware here:
https://github.com/englercj/resource-loader/blob/master/src/middlewares/caching/memory.js

        if (cache[resource.url]) {
            resource.data = cache[resource.url];
            resource.complete();
        }
        // if not cached, wait for complete and store it in the cache.
        else {
            resource.once('complete', function () {
               cache[this.url] = this.data;
            });

            next();
        }

Example does not call next(), if resource is cached and calls complete() on the resource instead.

However, it really seems that in that such case _boundOnLoad is never called and thus progress is stuck:
https://github.com/englercj/resource-loader/blob/master/src/Loader.js#L388

Am I missing something, or memory.js is not working as expected?

I was hoping to use the same approach to implement totally custom sound loading with howlerjs, like that:

        if (resource.loadType === PIXI.loaders.Resource.LOAD_TYPE.AUDIO) {
            var data = new Howl({
                urls: [resource.url],
                autoplay: false,
                onload: function() {
                    resource.data = data;
                    sounds[resource.name] = resource.data;
                    resource.complete();
                }
            });
        }
        else {
            next();
        }

Allow setting default middleware

It would be nice to have an API that registered "default middleware". That is, middleware that is automatically added to each loader that is created.

Cache busting

Previously raised here, I ended up overriding Resource.load to allow a cache busting querystring to be attached to all urls processed by the loader, regardless of whether they were added directly, or in-directly via custom parsers.

var oldLoad = PIXI.loaders.Resource.prototype.load;
PIXI.loaders.Resource.prototype.load = function(cb) {
    this.url += "?v=" + myVersionNumber
    return oldLoad.apply(this, [cb]);
}

This may be helpful to others using the resource-loader behind a CDN.

Cache-style middleware not working

Following the https://github.com/englercj/resource-loader/blob/master/src/middlewares/caching/memory.js middleware example, the following code should populate resource.data and not perform a network request. However, calling resource.complete() doesn't seem to stop the load from happening.

var Loader = require ('resource-loader');

var loader = new Loader();

var cache = {
    'example.json': {
        'test': 'one, two'
    }
};

loader
    .add('example.json')
    .before(function (resource, next) {
        if (cache[resource.url] != null) {
            resource.data = cache[resource.url];
            resource.complete();
        }

        console.log('calling next');
        next();
    })
    .load(function (loader, resources) {
        console.log('complete');
    });

I would expect this to simply call the complete callback with the cached data in the response.data, however it still tries to perform the web request.

Is the example code out of date? Or is it no longer possible to complete loads in the before middleware? I can't see anything in the code to check if the resource load was completed before making the load request.

multiple file loaded callback

Hello ,
I have some problem for loading multiple and trigger callback .

 PIXI.loader
    .add('loading1', '../common/images/loading/loading_logo1.json') 
    .add('loading2', '../common/images/loading/loading_logo2.json')
    .add('loading3', '../common/images/loading/loading_num.fnt', () => {
        // loading1 , loading2 not loaded first than loading3 every time
        loading.showLoading();
    })

so I use these code ....

PIXI.loader
    .add('loading_logo1.json', () => {
        PIXI.loader.add('loading_logo2.json', () => {
            PIXI.loader.add('loading_num.fnt', () => {
                // it works fine
                loading.showLoading();
            })
        })
    })

Does it has any better way ?

v2 Checklist

  • Allow arbitrary query strings for specific resources and all resources (#68)
  • Complete the skipped tests
  • Write a test to reproduce #66 and fix it
  • Implement a Font loader (#5)

IE9 troubles

I'm using latest version on pixi.js 3.0.7 and I'm having random stalls on IE9.
Same code works fine on IE10. There are no error events fired.
The Readme here says IE9 is a TODO, but pixi guys says it's ok.
Is this a known issue?

Strategy for loading and decoding audio files

Dear Sir!

I have question about how best to use the resource loader to load and decode audio files.
Here's the problem I'm trying to solve:

I have arrays of arbitrary file types that I need to load.
Some of them sometimes contain audio files, something like this:

filesToLoad = [
  "image.png",
  "blip.wav",
  "data.json",
  "music.mp3"
];

I can load them with the loader like this:

    this.loader
      .add(filesToLoad)
      .load(setupFunction);

But, I need the audio files to be loaded with an XHR responseType of "arraybuffer" and then passed to my local Web Audio API context's decodeAudioData method before being added to the loader's resources.

Is this something the resource loader can do?
Any advice on the strategy I should use to accomplish this would be greatly appreciated ๐Ÿ˜„

PS: Pixi's resource loader is awesome by the way, thanks so much, it's been incredibly fun to use!

Change .reset() to properly cancel running requests

As noted in https://github.com/pixijs/pixi.js/pull/2394, it would be nice if the reset functionality of the loader would properly cancel any running tasks. On reset, I would expect the following logic:

  • If a resource has not started loading, simply remove it from the queue
  • If a resource has started loading, cancel this process; if there has already been a network request, also call XMLHttpRequest.abort()
  • If the network request has completed, one should probably still run the corresponding "after"-middlewares (could also be made an option, open for debate)

What would be the use case for this?
Maybe an applications requests a large number of assets, some of which are needed right now and some of which will probably be needed soon. Then, however, the user makes a choice that switches the context of the application and instantly changes the required assets (or at least their priority). In this situation, one would probably want to stop any downloads currently in progress (at least the ones that have not started yet, but possibly all of them) to free up download spots for the assets that are actually needed right now (recall that both the browser and the resource loader have limits on the number of concurrent downloads).

This situation might occur when switching levels in a game or when providing a zoom functionality that uses different assets for different zoom levels (which is the motivation for this request).

Currently, loader.reset() does not cancel xhr requests. In the case of PIXI sprite sheets, this can also lead to a situation where there are _image resources in the resource cache that do not have a corresponding .json resource in the resource cache of the loader.

Maximum call stack size exceeded

If you load hundreds elements, especially with virtual resources (like ones created by spritesheetParser). The next callback is chainined, and could be called in the same frame (sync)

A workaround I found:

loader.pre((resource, next) => {
    setTimeout(next, 0);// break the call stack and delegate it to the next frame
});
// here others .pre(), .use(), .add(), etc.
loader.load(complete)

loader.reset() does not reset the resources table

I'm using this loader trough pixi and I want to reuse an existing Loader instance.

After I called the reset() method and reload some assets, I get an error:

Uncaught Error: Resource with name "images/game/[email protected]" already exists.

I think that is because the resources variable is not cleared on a reset.

no "complete" after "after"

Hello dear Sir,

after setting up some "after" events for middleware the whole loader is not sending any complete event anymore. Not using once, on nor by passing it to the load function itself.

Im not sure if this is wanted that way. But in fact I would love to have a global event that shows up after all of my loading, including my after-progressing is done. Just as it was back then with overloading-extending the old pixi JSONLoader class

Optional Keying of obejcts

We should make it so that a key is optional when adding itms to the loader. If the key is not provided then we can use the url as the key.

This will be super handy as it give us the best of both worlds ๐Ÿ‘

Cross-Site Scripting Vulnerability with Resource

We use HP Fortify to scan our code and the code of third party libraries and Fortify is reporting an issue in the Resource.prototype._xhrOnLoad function. The violation is a cross-site scripting vulnerability without input validation in the following snippet:

var div = document.createElement('div');
div.innerHTML = xhr.responseText;
this.data = div;

The problem is taking an ajax response and assigning it directly to inner html. If malicious content is sent back to the browser in the form of JavaScript, it may be executed, exploiting this vulnerability.

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.