I'm looking at the code of Polymers observe-js, and I can't quite grasp how it works. I'm not talking about the dirty checking, but on the invocation of it - when does the check being performed?
It looks like the magic is here:
var runEOM = hasObserve ? (function(){
return function(fn) {
return Promise.resolve().then(fn);
}
})() :
(function() {
return function(fn) {
eomTasks.push(fn);
};
})();
Since Promise.resolve().then(fn) invokes fn at the end of the callback stack this line defers fs, similarly to setTimeout(0, fn) or process.nextTick(fn)
But runEOM is never used in the file!
Can anybody spread light on this?
It seems that dirty checking is performed manually from the outside by calling the global.Platform.performMicrotaskCheckpoint interface method: Line 792
I think the concept is to notify observers manually after some piece of initial job is done or something in that clue.
Related
I don't know this is possible, but I have some special situations requiring it.
//Obj is a class with nothing.
Obj.prototype.v1 = function(){
//this is a normal statement.
//it could be something else
return 3;
}
//or it can be any way to declare a function:
var v1 = function(){return 3};
Obj.prototype.v2 = function(){
return this.v1()+2;
}
How to make it directly returns 3 here? It's like the function v1() is something like pseudocode this.return(3) for v2(), and certainly nothing can be reached after the first return.
If I'm generating the code dynamically and it has to be a return in the second function. (So it can easily get unexpected token for return (return 3).v2(), while trying to get the inside function to be called behaving like it's part of current function.)
Is there anyway to make this.v1() directly cause outside function v2() to return, for the first return it encounters? Preferably by focusing on modifying v1().
Is there anyway to make this.v1() directly cause outside function v2() to return, for the first return it encounters?
The idiomatic solution is to express this logic in v2. For example, you could cause v1 to modify a flag that decides what v2 does:
Obj.prototype.v1 = function(){
this.v1.continue = true; /* XXX: Continue? */
this.v1.continue = false; /* ... or not? */
return 3;
}
Obj.prototype.v2 = function(){
var ret_val = this.v1()+2;
if (!this.v1.continue) {
return;
}
/* XXX: Insert more code here */
}
We're talking about rather basic JavaScript here. Do you have a book?
Preferably by focusing on modifying v1().
I'm sure it's possible to circumvent the control of execution that v2 has when v1 returns in some situations, but that doesn't make it a good idea. Think about how difficult it'll become to debug this code!
For example, you could throw an error which v2 doesn't catch, and catch it further upstream. Such a hideous abuse of throw would be worse than the abuse of goto! Don't modify your code flow in such an unclear manner; it makes maintenance and debugging a nightmare!
Let's assume I have an AMD module that conditionally requires a second module in some environments:
define(["require"], function(require) {
var myObj = {
foo: console.error.bind(console)
};
if(browserEnv)
require(["./conditional-polyfill"],function(polyfill){
myObj.foo = console.log.bind(console,polyfill) ;
});
return myObj; //returns before conditional require is satisfied
});
The question is: How can I delay the define() call to return/callback AFTER the conditional require has been completed?
I.e. the code below fails:
require(["module-from-above"],function(logger){
logger.foo("Hello!"); //console.error gets called
});
My thoughts on solutions to this issue:
If I inline ./polyfill, everything would work. However, that just circumvents the problem and doesn't work for every case. I want it modularized for a reason.
I could return a Deferred object instead of myObj that gets fulfilled by ./conditional-polyfill later. This would work, but it's really ugly to call loggerDeferred.then(function(logger){ ... }); all the time.
I could make a AMD loader plugin for this module. And call the callback as soon as everything is ready. Again, this would work, but own loader plugins don't work with my build tool.
All solutions I can think of are more hacks than good code. However, I think that my issue isn't too far-fetched. So, how to handle this?
Push conditional outside of "factory function" (the name commonly used in AMD community to refer to the require's and define's callback function)
;(function() {
function factory(require, polyfill){
var myObj = {
foo: console.error.bind(console)
}
if(polyfill){
myObj.foo = console.log.bind(console, polyfill)
}
return myObj
}
var need = ['require']
if(browserEnv){
need.push("./conditional-polyfill")
}
define(need, factory)
})();
I would use a Deferred, as you say.
The deferred pattern is the ideal solution to this kind of issue, because it allows you to tie complex async operations together in a consistent way.
It will make your code a bit larger, but its a simple solution compared to modifying the loader and the build tools.
This question isn't exactly typescript related but without the context it would be unclear why I would even require such behavior. Should be relatively straight forward to understand whether you know Typescript or not.
I have a dialog class implementation in Typescript that looks something like this (only showing relevant methods and fields):
class BaseDialog{
...
public dialogEl: JQuery;
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined)
this.dialogEl.load(route);
return this;
}
public HtmlLoadContent(html: string) {
if (this.dialogEl !== undefined)
this.dialogEl.empty().html(html);
return this;
}
public Show() {
if (this.dialogEl !== undefined)
this.dialogEl.dialog("open");
}
...
}
I'm returning this from AjaxLoadContent() and HtmlLoadContent() so that I can chain a call to Show() as follows:
var dialog = new BaseDialog();
dialog.AjaxLoadContent("/Account/Login").Show(); //Ajax call
dialog.HtmlLoadContent(someHtml).Show(); //Load from variable, no ajax call
I find this chaining syntax very clean and logical so I want to stick with it, however, in the ajax scenario, Show() gets called before ajax load() completes so the dialog opens, then there is a delay before the content appears. I can't provide a callback to load() since I'd like to explicitly chain Show() onto the call instead of calling it internally...therefore, I need some kind of synchronous mechanism.
I'm now looking into Frame.js to accomplish this "synchronous" style without hanging the browser with something like $.ajaxSetup({async: false;}). Here is the answer I was hoping would work: https://stackoverflow.com/a/10365952
However, the following code still has the delay:
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined){
var that = this;
Frame(function (next) {
$.get(route, next);
});
Frame(function (next, response) {
that.dialogEl.html(response); //Breakpoint 1
});
Frame.init();
return this; //Breakpoint 2
}
}
However this doesn't seem to work as Breakpoint 2 gets hit first despite the explicit control flow I've defined. The Show() call happens immediately after return this (therefore loading a blank dialog), then finally that.jQueryDialog.html(response) gets called from the second Frame, loading the content after the dialog has already been shown (therefore still a delay).
How can I accomplish this synchronous behavior?
This is exactly (IMO) what JQueryDeferred is for. You can use that for all this without needing to add another dependency on Frame.js. The easiest way to do this would be to return a JQueryPromise from each Async method, like so:
///<reference path="./jquery.d.ts">
class BaseDialog{
public dialogEl: JQuery;
public AjaxLoadContent(route: string):JQueryPromise {
var deferred = $.Deferred();
if (this.dialogEl !== undefined)
this.dialogEl.load(route)
.done(() => deferred.resolve())
.fail(() => deferred.reject());
return deferred.promise();
}
public HtmlLoadContent(html: string):void {
if (this.dialogEl !== undefined) {
this.dialogEl.empty().html(html);
}
public Show():void {
if (this.dialogEl !== undefined)
this.dialogEl.dialog("open");
}
}
var dialog = new BaseDialog();
dialog.AjaxLoadContent("something")
.done(() => dialog.Show());
That's not quite as clean an interface, but the alternative is to do some awfully clever coding whereby your class throws each Deferred into a FIFO queue, and each subsequent method waits on the previous Deferred in the queue before it starts executing. Certainly possible, and if you're designing this API for significant external consumption, it might be worth doing. But if you're just planning to use it for some internal project, it sounds like too much work and maintenance to me. (Just my opinion, of course :-).
(Other problems with your proposed interface: (1) it doesn't have any way of handling errors, analagous to the JQueryDeferred.fail() handler; and (2) it doesn't have any way of doing any external processing in-between calls to your class. What if you wanted to do a transform on the content before you called the Show() method?)
"However this doesn't seem to work as Breakpoint 2 gets hit first despite the explicit control flow"
Actually the flow control is working exactly as you have written it. Only things inside the Frame functions will be controlled by Frame. You can not use return statements inside of callbacks and expect them to return the calling function.
Ken's answer is correct that the use of jQuery Deferred will accomplish the same goal as Frame does in your above example. Frame is designed for sequences much longer than the one you have created. Either will behave the same way, the major difference is syntax.
Honestly, I think the delay you are experiencing is the time it takes to make the AJAX call. Maybe I am not understanding your question, but the Frame part looks right. Here are a few notes:
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined){
var that = this;
Frame(function (next) {
$.get(route, next); // great!
});
Frame(function (next, response) { // good use of passing variables!
that.dialogEl.html(response); // yep, will happen synchronously!
// return that; // unfortunately, this would only return 'that'
// to Frame, not to AjaxLoadContent.
// It's not possible to return the calling function
// from inside a callback.
next(); // the callback should be called here
// to complete the Frame sequence.
});
Frame.init();
return this; // notice that the return statement here is not in Frame?
}
}
I need to rewrite a JavaScript function with Fiddler. I believe this answer partially addresses the problem; however, I'm still searching for RegEx information. For example:
function traceThis(message) {
//setTimeout(function() { window.opener.childWindowMessageHandler(message);}, 100);
//if (!window.console) console = {};
//console.log(message);
}
needs to become:
function traceThis(message) {
setTimeout(function() { window.opener.childWindowMessageHandler(message);}, 100);
if (!window.console) console = {};
console.log(message);
}
I imagine it would be simpler to match and replace the individual lines within the traceThis() function; however, I think it would be most useful to learn how to select and replace any desired function from the "function" to its closing "}" regardless of statements within it.
HBP's answer won't work, because the toString() function isn't available until the script is actually running. But he does point to a simple way to solve this problem that probably won't require either a JS parser or a complicated Regular Expression.
Namely, simply do a straight string-replacement of:
function traceThis(message) {
with
// Here's my NewFunction
function traceThis(message)
{
// My new instructions here
}
function OriginalVersionOfTraceThis(message) {
That way, when your injector runs, it overwrites the front of the old function with your desired script code, and renames the old function to something else (that will never be called).
The source of a function can be gotten by traceThis.toString () From there you can do whatever changes you want then recreate the function using new Function
I have an application that uses Ajax.Request and its onSuccess event handler in lots of places.
I need to call a function (that will check the response) before all these onSuccess events fire. I tried using Ajax.Responders.register with onComplete event but it fires after Ajax.Request's onSuccess event. Any suggestions?
similar to Aleksander Krzywinski's answer, but I believe this would prevent you from having to sprinkle the use of "wrap" everywhere, by consolidating it to the onCreate Responder.
Ajax.Responders.register({
onCreate: function(request) {
request.options['onSuccess'] = request.options['onSuccess'].wrap(validateResponse);
}
});
There are several events to chose from. Here is the event chain for Ajax.Request:
onCreate
onUninitialized
onLoading
onLoaded
onInteractive
onXYZ, onSuccess or onFailure
onComplete
onLoading, onLoaded, onInteractive sound interesting, but according to the spec they are not guaranteed to happen. That leaves you with the possibility to hook on to onCreate, which is called just after the request object is build, but before the request is actually made.
This might be a little late, but for the benefit of anyone else wondering about the same problem I will propose this solution:
You can use Prototypes own implementation of aspect-oriented programming to do this. Granted you will have to modify all your onSuccess-parameters, but it can be done with a simple search-and-replace, instead of updating all your callback functions. Here is an example Ajax.Request creation:
new Ajax.Request('example.html', {
parameters: {action: 'update'},
onSuccess: this.updateSuccessful
});
Say you have similar code snippets spread all over your code, and you want to preceed them all with a certain function that validates the response before the actual function is run(or even prevented from running at all). By using Funtion.wrap supplied in Prototype we can do this by extending the code above:
new Ajax.Request('example.html', {
parameters: {action: 'update'},
onSuccess: this.updateSuccessful.wrap(validateResponse)
});
Where 'validateResponse' is a function similar to this:
// If you use the X-JSON-header of the response for JSON, add the third param
function validateResponse(originalFn, transport /*, json */) {
// Validate the transport
if (someConditionMet) {
originalFn(transport /*, json */);
}
}
Thus you have extended your onSuccess-functions in one central place with just a quick search for onSuccess and pasting in 'wrap(validateResponse)'. This also gives you the option of having several wrapper-functions depending on the needs of the particular Ajax-request.
You can run your method before the other code in onSuccess and return false if something is wrong.
Don't know if this is the cleanest solution, but for me it did the trick.
var tmp = Ajax.Request;
Ajax.Request = function(url, args) {
// stuff to do before the request is sent
var c = Object.clone(args);
c.onSuccess = function(transport){
// stuff to do when request is successful, before the callback
args.onSuccess(transport);
}
var a = new tmp(url, c);
return a;
}
Ajax.Request.protoype = new tmp();
Ajax.Request.Events = tmp.Events;
delete tmp;
"General solution" - independent upon JS framework (kind of)
var oldFunc = Ajax.Request.onSuccess;
Ajax.Request.onSuccess = function foo() {
alert('t');
oldFunc.apply(this, arguments);
}
This will "extend" your JS function making it do exactly what it used to do except show an alert box every time before it executes...