понедельник, 26 марта 2018 г.

Ошибка System.js traceur.js 404 Not Found - Как исправить - Инструкция

При загрузке файлов с помощью SystemJS часто возникает ошибка:
http://localhost:8000/traceur 404 (Not Found)

Возникает она, как правило, из-за того, что скорее всего в своем коде вы с помощью многострочных комментариев закомментировали импорты в своих файлах/

/*
import SomeThing from 'somewhere';
*/

В коде файла system.js есть регулярное выражение, которое обнаруживает закомментированные импорты и пытается из обработать, что приводит к ошибке.

var esmRegEx = /(^\s*|[}\);\n]\s*)(import\s*(['"]|(\*\s+as\s+)?[^"'\(\)\n;]+\s*from\s*['"]|\{)|export\s+\*\s+from\s+["']|export\s*(\{|default|function|class|var|const|let|async\s+function))/;

Для того. чтобы ошибку устранить вам надо удалить закомментированные импорты из вашего кода.

Или, если вам надо оставить комментарии, то чтобы ошибка не проявлялась, просто добавьте кавычки вокруг слова import.

/*
"import" SomeThing from 'somewhere';
*/

В крайнем случае в конфиге tsconfig.json для TypeScript можно прописать настройку, чтобы он не оставлял в коде комментарии при транспиляции.

{
    "compilerOptions": {
        "removeComments": true
    }
}

Также ошибка может быть вызвана тем, что вы пытаетесь загрузить в своем коде некорректный UMD-файл.

Убедитесь также, что вы загружаете JavaScript, а не TypeScript-файлы.

среда, 21 марта 2018 г.

Вынос внешних файлов из сборки Webpack

Файл webpack.config.js

const path = require('path')
        , CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = [
    {
          entry: path.resolve(__dirname, 'src/index.js')
        , output: {
              path: path.resolve(__dirname, 'dist')
            , filename: 'bundle.js'
          }
        , externals: { // Модули, которые надо из итогового файла сборки исключить. Они будут загружаться отдельно.
              './my-module.js': 'a'
            , './lodash.js': '_' // Заменить импорт модуля на имя этой глобальной перемеменной: require('lodash') --> var _ В итоговый файл попадет: {1: function (...) {module.exports = _;}}
            , './jquery.js': '$' // Заменить импорт модуля на имя этой глобальной перемеменной: require('jquery') --> var jQuery В итоговый файл попадет: {1: function (...) {module.exports = jQuery;}}
          }
        , plugins: [
              new CleanWebpackPlugin(['dist'])
          ]
        , bail: true
    }
];

Файл index.js

import a from './my-module.js';
import * as _ from './lodash.js';
import * as $ from './jquery.js';

a();
console.log(_.tail([1, 2, 3]));
console.log($);

Файл my-module.js

export function a () {
    console.log(1);
}

Скомпилированный файл my-module-compiled.js

function a () {
    console.log(1);
}

Файл index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <script src="src/my-module-compiled.js"></script>
    <script src="src/lodash.js"></script>
    <script src="src/jquery.js"></script>
    <title>Webpack App</title>
  </head>
  <body>
    <script src="dist/bundle.js"></script>
  </body>
</html>

Система преобразования типов в JavaScript.

Система преобразования типов в JavaScript очень простая.

В JavaScript есть всего 3 приведения типов:

1) Строковое - String() - приведение к строке в строковом контексте. Происходит, например, при конкатенации строк ("abc" + 10). Строковое преобразование происходит при необходимости представления чего-либо в виде строки.

2) Числовое - Number() - приведение к примитиву в числовом контексте, включая унарный плюс (+value). Происходит при сравнении разных типов (==, !=, >=, <=). Числовое преобразование происходит в математических выражениях (_, *, /, %), а также при сравнении.

3) Логическое - Boolean() - приведение к логическому типу в логическом контексте (if, &&, ||). Логическое преобразование происходит при приведение к true и false в логическом контексте, например в условиях и при применении логических операторов. Все значения, которые можно трактовать как пустые, становятся false: пустая строка, 0, null, undefined, NaN. Все остальное трактовать как true.

Особым случаем является проверка на равенство таких специальных типов как Null и Undefined. Они равны только друг другу и неравны всему остальному:

null == null
undefined == undefined
undefined == null
null == undefined

В JavaScript логическое преобразование особенно интересно своим сочетанием с числовым.

Приведем пример.

var a = 0;
var b = "0";
console.log(a == b); // true

Когда мы сравниваем число 0 и строку "0", то мы сравниваем их не в логическом контексте, а в числовом.
Поэтому у нас получается такое сравнение с преобразованием типов:

console.log(Number(0) == Number("0")); // true

Разберем другой код:

var bool = new Boolean(false); // bool = object
if (bool) {console.log(bool);} // Boolean(bool) = true, поэтому if (true) {console.log(false);}
if (bool == false) {console.log(bool);} // bool.valueOf() = false, поэтому if (false == false) {console.log(false);}

Мы используем класс Boolean, который создает не примитив, а объект bool - экземпляр класса Boolean.
Если bool  -  это объект, то в логическом контексте он всегда будет приведен к true.
Если мы производим сравнение, то тут сработает числовое сравнение, при котором будет вызван метод bool.valueOf().

пятница, 16 марта 2018 г.

Browser XMLHttpRequest and Node Server

Файл server.js

var http = require('http')
    , fs = require('fs')
    , path = require('path')
    , url = require('url')
    , querystring = require('querystring');

var server = http.createServer();

server.on('request', function (request, response) {
    if (request.method === 'POST' && url.parse(request.url).path === '/ajax') {
        var data = [];
        request.on('data', function (chunk) {data.push(chunk)});
        request.on('end', function () {
            setTimeout(function () {
                response.writeHead(200, {'Content-Type': 'text/plain'});
                var query = querystring.parse(data.join());
                response.end(query.data);
            }, 1000);
        });
    } else {
        fs.readFile(path.resolve(path.join(__dirname, 'index.html')), function (error, indexHTML) {
            if (error) {throw error;}
            response.writeHead(200, {'Content-Type': 'text/html'});
            response.end(indexHTML);
        });
    }
});

server.listen(80, '127.0.0.1', function (error) {
    if (error) {throw error;}
    console.log('Server started at 127.0.0.1:80');
});

Файл index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>XMLHttpRequest</title>
</head>
<body>
    <div id="server-response"></div>
    <script type="text/javascript">
        setTimeout(function () {
            var request = new XMLHttpRequest();
            if (request.readyState === 0) {
                console.log('readyState 0 UNSENT: ' + (request.readyState === request.UNSENT));
            }
            request.open('POST', '/ajax', true, 'username', 'password');
            if (request.readyState === 1) {
                console.log('readyState 1 OPENED: ' + (request.readyState === request.OPENED));
            }
            request.onreadystatechange = function () {
                if (request.readyState === 2) {
                    console.log('readyState 2 HEADERS_RECEIVED: ' + (request.readyState === request.HEADERS_RECEIVED));
                }
                if (request.readyState === 3) {
                    console.log('readyState 3 LOADING: ' + (request.readyState === request.LOADING));
                }
                if (request.readyState === 4) {
                    console.log('readyState 4 DONE: ' + (request.readyState === request.DONE));
                }
                if (request.readyState === 4) {
                    var response = this;
                    if (response.status === 200) {
                        document.getElementById('server-response').innerHTML = (
                               '<p>RESPONSE STATUS:</p>'
                            + '<p>' + response.status + '</p>'
                            + '<p>RESPONSE STATUS TEXT:</p>'
                            + '<p>' + response.statusText + '</p>'
                            + '<p>HEADERS:</p>'
                            + '<p>' + response.getAllResponseHeaders() + '</p>'
                            + '<p>HEADER CONTENT_TYPE:</p>'
                            + '<p>' + response.getResponseHeader('Content-Type') + '</p>'
                            + '<p>RESPONSE URL:</p>'
                            + '<p>' + response.responseURL + '</p>'
                            + '<p>RESPONSE:</p>'
                            + '<p>' +response.response + '</p>'
                            + '<p>RESPONSE TEXT:</p>'
                            + '<p>' + response.responseText + '</p>'
                        );
                    } else {
                        document.getElementById('server-response').innerHTML = 'Error. Status code: ' + response.status + ', status text: ' + response.statusText;
                    }
                }
            };
            request.timeout = 2000;
            request.ontimeout = function () {document.getElementById('server-response').innerHTML = 'Timeout'};
            request.onabort = function () {document.getElementById('server-response').innerHTML = 'Abort'};
            request.onerror = function (event) {document.getElementById('server-response').innerHTML = 'Error. Server is not available. Status code: ' + event.target.status;};
            if (request.overrideMimeType) {request.overrideMimeType('text/plain', 'x-user-defined');}
            request.setRequestHeader('My-Header', 'abcdef');
            request.withCredentials = true;
            request.responseType = 'text';
            request.send('data=123&value=456');
            setTimeout(function () {request.abort();}, 500);
        }, 5000);
    </script>
</body>
</html>

четверг, 15 марта 2018 г.

new XMLHttpRequest()

var xhr = new XMLHttpRequest();

xhr.open('POST', 'http://www.site.com/', true, 'username', 'password');

xhr.withCredentials = true;

xhr.timeout = 120000;

xhr.setRequestHeader('My-Header', '123');

xhr.overrideMimeType('text/plain; charset=x-user-defined');

xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200 || xhr.status === 0) {
            console.log('status: ' + xhr.status === 1223 ? 204 : xhr.status);
            console.log('statusText: ' + xhr.status === 1223 ? 'No Content' : xhr.statusText);
            console.log('getAllResponseHeaders: ' + xhr.getAllResponseHeaders());
            console.log('getResponseHeader: ' + xhr.getResponseHeader('Content-Type'));
            console.log('responseText: ' + xhr.responseText);
        } else {
            console.log('Error in request.');
        }
    }
};

xhr.onabort = function () {
    if (!xhr) {return;}
    xhr = null;
    console.log('Aborted.');
};

xhr.ontimeout = function () {
    xhr = null;
    console.log('Timeout.');
};

xhr.onerror = function (error) {
    xhr = null;
    console.log('Error.');
    console.log(error.message);
};

xhr.send(JSON.stringify({a: 1, b: 2}));

setTimeout(function () {
    if (xhr) {xhr.abort();}
}, 1000);

понедельник, 5 марта 2018 г.

AJAX загрузка картинок

<html>
<body>
<script language="javascript" type="text/javascript">
    function send_with_ajax ( ) {
        if (window.XMLHttpRequest || window.ActiveXObject) {
            if (window.ActiveXObject) {
                try {
                    xhr = new ActiveXObject("Msxml2.XMLHTTP");
                } catch(exception) {
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");
                }
            } else {
              xhr = new XMLHttpRequest();
            }
        } else {
            alert("Your browser does not support XMLHTTP Request...!");
        }

        xhr.open("GET", "300x300.gif", true);   // Make sure file is in same server
        xhr.overrideMimeType('text/plain; charset=x-user-defined');
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4){
                if ((xhr.status == 200) || (xhr.status == 0)){
                    var image = document.getElementById("get_img");
                    image.src = "data:image/gif;base64," + encode64(xhr.responseText);
                }else{
                    alert("Something misconfiguration : " +
                        "\nError Code : " + xhr.status +
                        "\nError Message : " + xhr.responseText);
                }
            }
        };
        xhr.send(null);
    }

    function encode64 (inputStr) {
       var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
       var outputStr = "";
       var i = 0;
     
       while (i> 2;
          var enc2 = ((byte1 & 3) << 4) | (byte2 >> 4);
         
          var enc3, enc4;
          if (isNaN(byte2)){
            enc3 = enc4 = 64;
          } else{
            enc3 = ((byte2 & 15) << 2) | (byte3 >> 6);
            if (isNaN(byte3)){
               enc4 = 64;
            } else {
                enc4 = byte3 & 63;
            }
          }
          outputStr +=  b64.charAt(enc1) + b64.charAt(enc2) + b64.charAt(enc3) + b64.charAt(enc4);
       }
       return outputStr;
    }
</script>

<button onClick="send_with_ajax()">Get Image</button><br />
<img id="get_img" />
</body>
</html>

пятница, 2 марта 2018 г.

Node.js - Краткая шпаргалка по работе с файлами

const fs = require('fs');

// Создать, переименовать или переместить, прочитать содержимое, удалить директорию.

fs.mkdir('test-dir', 0o777, function (error) {if (error) {throw error;}
    fs.rename('./test-dir', './other-dir', function (error) {if (error) {throw error;}
        fs.readdir('./other-dir', {encoding: 'utf8'}, function (error, files) {if (error) {throw error;}
            console.log(files);
            fs.rmdir('./other-dir', function (error) {if (error) {throw error;}});
        });
    });
});

// Создать или записать, дописать, обрезать, прочитать содержимое, переименовать или переместить, скопировать, удалить файл.

fs.writeFile('test-file.txt', 'Hello world', {encoding: 'utf8', mode: 0o666, flag: 'w'}, function (error) {if (error) {throw error;}
    fs.appendFile('./test-file.txt', ' and home', {encoding: 'utf8', mode: 0o666, flag: 'a'}, function (error) {if (error) {throw error;}
        fs.truncate('./test-file.txt', 5, function (error) {if (error) {throw error;}
            fs.readFile('./test-file.txt', {encoding: 'utf8', flag: 'r'}, function (error, data) {if (error) {throw error;}
                console.log(data);
                fs.rename('./test-file.txt', './other-file.txt', function (error) {if (error) {throw error;}
                    fs.link('./other-file.txt', './test-file.txt', function (error) {if (error) {throw error;}
                        fs.unlink('./other-file.txt', function (error) {if (error) {throw error;}
                        });
                    });
                });
            });
        });
    });
});

// Изменить права доступа, узнать время создания и изменения, изменить время создания и изменения, узнать полный путь файла.

fs.chmod('./test-file.txt', 0o777, function (error) {if (error) {throw error;}
    fs.access('./test-file.txt', fs.constants.R_OK | fs.constants.W_OK, function (error) {
        if (error) {console.log('No access!');} else {console.log('Can read | write');}
        fs.stat('./test-file.txt', function (error, stat) {if (error) {throw error;}
            console.log(stat.birthtime);
            fs.utimes('./test-file.txt', (new Date().getTime() + 20000) / 1000, (new Date().getTime() + 50000) / 1000, function (error) {if (error) {throw error;}
                fs.realpath('./test-file.txt', {encoding: 'utf8'}, function (error, resolvedPath) {if (error) {throw error;}
                    console.log(resolvedPath);
               });
            });
        });
    });
});

// Открыть, записать, закрыть файл.

fs.open('./test-file.txt', 'w', 0o666, function (error, fd) {if (error) {throw error;}
    const dataBuffer = Buffer.from('abcdefghijklmnopqrstuvwxyz');
    const dataBufferSize = dataBuffer.length;
    let chunkBufferSize = 2; // in bytes
    let chunkBuffer = dataBuffer.slice(0, chunkBufferSize);
    let totalBytesWritten = 0;
    const offset = 0;
    function writeDataToFile () {
        if (totalBytesWritten < dataBufferSize) {
            fs.write(fd, chunkBuffer, offset, chunkBufferSize, totalBytesWritten, function (error, chunkBufferBytesWritten, buffer) {if (error) {throw error;}
                totalBytesWritten += chunkBufferSize;
                if ((totalBytesWritten + chunkBufferSize) > dataBufferSize) {
                    chunkBufferSize = dataBufferSize - totalBytesWritten;
                }
                chunkBuffer = dataBuffer.slice(totalBytesWritten, totalBytesWritten + chunkBufferSize);
                writeDataToFile();
            });
        } else {
            fs.close(fd, function (error) {if (error) {throw error;}
            });
        }
    }
    writeDataToFile();
});

// Открыть, прочитать, закрыть файл.

fs.open('./test-file.txt', 'r', function (error, fd) {if (error) {throw error;}
    fs.fstat(fd, function (error, stat) {if (error) {throw error;}
        const fileSize = stat.size;
        let fileBuffer = Buffer.alloc(fileSize);
        let chunkBufferSize = 2; // in bytes
        let totalBytesRead = 0;
        function readDataFromFile () {
            if (totalBytesRead < fileSize) {
                if ((totalBytesRead + chunkBufferSize) > fileSize) {
                    chunkBufferSize = fileSize - totalBytesRead;
                }
                fs.read(fd, fileBuffer, totalBytesRead, chunkBufferSize, totalBytesRead, function (error, chunkBytesRead, buffer) {if (error) {throw error;}
                    totalBytesRead += chunkBufferSize;
                    console.log(buffer.toString('utf8'));
                    readDataFromFile();
                });
            } else {
                fs.close(fd, function (error) {if (error) {throw error;}
                });
            }
        }
        readDataFromFile();
    });
});

// Поток записи в файл.

const writeStream = fs.createWriteStream('./test-file.txt', {encoding: 'utf8', mode: 0o666, flags: 'w', fd: null, autoClose: true});
writeStream.on('error', function (error) {throw error;});
writeStream.on('open', function () {console.log('writeFile opened');});
writeStream.on('close', function () {
    console.log('bytesWritten: ' + writeStream.bytesWritten + ' | path: ' + writeStream.path);
    console.log('writeFile closed');
});
writeStream.write('some');
writeStream.write(' data');
writeStream.end();

// Поток чтения из файла.

const readStream = fs.createReadStream('./test-file.txt', {encoding: 'utf8', mode: 0o666, flags: 'r', fd: null, autoClose: true});
readStream.on('error', function (error) {throw error;});
readStream.on('open', function () {console.log('readStream open');});
readStream.on('data', function (data) {console.log(data + ' | bytesRead: ' + readStream.bytesRead + ' | path: ' + readStream.path);});
readStream.on('end', function (data) {console.log(data + ' | readStream end');});
readStream.on('close', function () {console.log('readStream closed');});

// Отслеживать изменения в файле.

// Первый способ.

function watchHandler (current, previous) {
    console.log('Current mtime:' + current.mtime + ' | Previous mtime: ' + previous.mtime);
}
fs.watchFile('./test-file.txt', {persistent: true, interval: 5007}, watchHandler);
fs.unwatchFile('./test-file.txt', watchHandler);

// Второй способ.

const watcher = fs.watch('./test-file.txt', {encoding: 'utf8', persistent: true, recursive: true});
watcher.on('error', function (error) {throw error;});
watcher.on('change', function (eventType, filename) {
    console.log(eventType);
    if (filename) {console.log(filename);}
    watcher.close();
});