All streams
Search
Write a publication
Pull to refresh
11
0
Send message
А надо ли рендерить то, что перед текущей страницей? Может просто поместить туда один пустой div с высотой в сколько-то страниц, и рендерить там только в случае если пользователь листает вверх.
Да, точно, умотал вниз, потом перезагрузил, так как тормоза от перезагрузки обычно проходят. Но вообще у меня вроде быстрый десктоп. Может не стоит и пытаться рендерить слишком много, или сделать какое-то ограничение по-времени?
Что он так долго делает?
Когда разработчики JS уберут ключевые слова async/await, чтобы было так же как и во всех остальных языках (естественно, чтобы это не создавало блокировок event-loop), тогда этот велосипед будет не нужен.

А пока в nsynjs я могу просто писать последовательный неблокирующий останавливаемый код, а async/await вычисляются автоматически:
    var fh = new textFile();
    fh.open('../data/lorem.txt');
    var s;
    while (typeof(s = fh.readLine(synjsCtx).data) != 'undefined')
    {
        if(s)
            console.log(s);
        else
            console.log("<empty line>");
        wait(synjsCtx,1000);
    }
    fh.close();
исходник
Здается мне, в стеке сидят только указатели для локальных переменных, ну и скорее всего примитивы с известным размером типа number или boolean, А все остальное все равно придется хранить в куче.
Прочитал статью, еще больше полюбил цикл for (и goto).
Event loop в nsynjs это просто цикл while(...) {...}, который выполняется в главном jS-потоке. Этот цикл выполняет свои тики пока не встретит вызов функции. Указатель на функцию анализируется на предмет типа функции и надо ли подождать, и если надо, то просто цикл останавлиавается по break. Это похоже на невытесняющую многозадачность, но все происходит внутри одного процесса JS. Поэтому вебворкеры здесь вообще ни при чем.

зачем в принципе нужно «отслеживать активные обертки»
в случае, если псевдопоток nsynjs завершается извне (типа как по SIGHUP), и надо освободить ресурсы, инача они вызовут колбеки. Стандартный JS такие возможности не предоставляет, ну тоесть надо писать учет активных функций самому. Но раз уж у нас есть свой event-loop и свои стеки, то почему бы не реализовать чтобы это делалось автоматически?
Javascript неспроста движется в сторону проверки всего и вся при компиляции

В JS изначально даже var не было, да и сейчас практически все резольвятся в рантайме, поэтому я бы не стал брать JS в качестве примера как надо делать типизацию.

прелесть промисов в явном, детерминированном управлении event loop — см. концепции greenlets, fibers и т.д. В nsynjs этого нет, и по дизайну невозможно.
в nsynjs свой event loop, а также свои структуры с программными счетчиками, стеками, локальными переменными, closures и т.п.

Наверное, я неправильно использовал промисы все это время?

Имеется ввтиду внутри промисифицированных функций, или если промис вернули куда-то в не async-функцию

В чем отличие от запущенной async-функции?
в том что есть указатель на ее состояние, с её собственным event-loop-ом, по которому над ней можно иметь полный контроль.

В чем отличие от bluebird, который умеет отменять исполняющиеся промисы?

В блюберд придется писать код чтобы отслеживать активные промисы. Хотя это и не сложно. В нативных промисах этого нет, и, говорят, не будет.

В чем отличие от обертки try/finally внутри тела async-функции, с clearTimeout внутри finally?
Это придется делать везде, где вызывается промис с setTimeout? Либо делать async-обертку к промису, ну и отслеживать активные обертки. В nsynjs это делается автоматически, т.к. есть свой стек, по которому можно всегда узнать что сейчас активно.

А за асинхронные конструкторы, как по уму, надо бы отрывать руки по самые ягодицы.
Не буду холиварить. Видел их много раз, и не сказал бы, что изза них какие-то существенные проблемы. Это как goto, кому-то нравится, кому-то нет…
В процессе более активного использования nsynjs список отличий от async/await сформировался такой:

— в nsynjs нет надобности использовать ключевые слова async/await в коде, так как тип исполняемой функции проверяется в рантайме
— в nsynjs отпадает надобность в промисах в принципе (хотя для поклонников можно добавить несколько строчек в код nsynjs чтобы проверять возвращаемый функцией результат в рантайме на предмет не промис ли он, и не надо ли подождать).
— в nsynjs для исключительных ситуаций достаточно механизма try/catch/throw. Механизм Promise/then/catch/reject не нужен.

Преимущества по-сравнению с async/await:

— возможность запускать псевдо-потоки,
— возможнось останавливать псевдо-потоки как изнутри, так и извне,
— возможнось подчистить активные функции с колбеками при остановке потока извне (например на активный setTimeout автоматически вызвать clearTimeout),
— возможность создавать конструкторы с асинхронными функциями внутри.
Удачи вам в моем родном городе. С таким позитивным настроем у вас и дальше все будет получаться. Посоветую только держать все документы (и российские, и украинские) всегда в порядке, т.к. никогда не знаешь на какой границе через сколько лет что могут потребовать.
Как-то проходил у них тех. интервъю удаленно (на телефоне с писанием задачки на Java в режиме шеринга). Не перезвонили…
Да, модули можно передавать в параметрах в синхронный код. Это так и сделано, например в файле user.js:
...
var wrappers = require('./wrappers');
nsynjs.run(synchronousCode,{},wrappers,function (m) {
    module.exports = m;
});

Можно и так, и так, кому как больше нравится.
В нативном require в node модули можно тоже грузить несколькими способами.
Может опубликуете в NPM?

В NPM он есть: npm install nsynjs, и можно require('nsynjs');

require.main.require( './user' )

require, как оказалось, работает немного не так как хотелось бы с относительными путями: путь берётся относительно файла, из которого вызвана require. В случае nsynjs это значит будет относительно местоположения nsynjs.js, Пока непридумал как это победить, но наткнулся на require.main.require, которое позволяет искать относительно от начального файла приложения. require.main.require нужно только для синхронного кода.

Может сделать это универсальным враппером идущим с самой библиотекой?
Да, наверное можно врапперы нескольких самых общеупотребительных функций в нее включить
Вот такое решение получилось:

index.js
var nsynjs = require('../../nsynjs');

function synchronousApp(modules) {
	var user = require.main.require( './user' );
	var greeter = require.main.require( './greeter' );

    try {
        console.time('time');
        greeter.say('Hello', user);
        greeter.say('Bye', user);
        console.timeEnd('time');
    }
    catch(e) {
        console.log('error',e);
    }
}

nsynjs.run(synchronousApp,null,function () {
		console.log('done');
});



user.js
var nsynjs = require('../../nsynjs');

var synchronousCode = function (wrappers) {
    var config;

    var getConfig = function() {
        if( !config )
            config = JSON.parse(wrappers.readFile(synjsCtx, 'config.json').data);

        return config;
    };
    return {
        getName: function () {
            return getConfig().name;
        }
    };
};

var wrappers = require('./wrappers');
nsynjs.run(synchronousCode,{},wrappers,function (m) {
    module.exports = m;
});



greeter.js
var nsynjs = require('../../nsynjs');

var synchronousCode = function(){
    return {
        say: function ( greeting , user ){
            console.log( greeting + ', ' + ( user.getName() ) + '!' )
        }
    };
};

nsynjs.run(synchronousCode,{},function (m) {
    module.exports = m;
});



wrappers.js
var fs=require('fs');
exports.readFile = function (ctx,name) {
	console.log("reading config");
    var res={};
	fs.readFile( name, "utf8", function( error , configText ){
		if( error ) res.error = error;
		res.data = configText;
		ctx.resume(error);
	} );
    return res;
};
exports.readFile.synjsHasCallback = true;


Я его добавил в примеры в последнюю версию на гитхабе и в NPM, можно запускать прямо оттуда.
Время выполнения:
на десктопе i7 4790k, node v6.9.4: 3.5ms,
на ноутбуке i7 3630qm, node v6.9.4: 6.5ms,

У вас по-ссылке какие-то ошибки вместо кода, раньше вроде так не было…
Вы бы себя слышали :)

А что я такого сказал? Структура с данными есть, контроль над исполнением тоже есть, причем полный. Исполняем шаг — рендерим структуру. В чем проблема?

Ох… Ну а если я под Node?
Под нодой можно поднять http-сервер в том же процессе, что и приложение, и в нём точно также рендерить все на странице, которую смотреть с браузера. Понятно, что тут надо подумать, как лучше организовать код чтобы 2 раза не писать рендеринг, но принципиальных препядствий этому я не вижу.
А как вы планируете его делать?

Дебаггер можно отображать на динамическом div-е. Для этого нужно для каждого элемента языка в прототипы добавить функцию, которая бы выводила в смотрибельном виде данные о текущем состоянии из контекста. Ну и кнопки пошагового исполнения добавить. В общем это тривиальная задача по отображению разнородных данных из дерева на странице.
Надо перенести и декларацию, и использование функции внутрь синхронного кода:

	function synchronousCode() {
		function withParam(param) {
		   return function() {
			 console.log(param);
		   }
		};

		withParam('test')();
	}

	nsynjs.run(synchronousCode,{}, function (r) {
		console.log('Done');
	});


Это связано с тем, что функции, определенные внутри синхронного кода, не работают с нативными переменными, а вместо этого модифицируются движком и используют хэш в контексте потока. Поэтому тело такой функции можно использовать только внутри синхронного кода.
Дебаггера под это пока нет. При надобности может сделаю, это будет не такая большая работа, по сравнению с уже проделанной.
Typescript — отличная вещь для отлавливания багов, связанных с динамической природой типов данных в JS, Но проблему колбеков он никак не решает.
Думаю теперь можно, пришлю на днях.

Information

Rating
Does not participate
Registered
Activity