I'm trying to chain jquery deferreds such that a promise is resolved by another Deferred.
My use case is: I have an object that returns a promise to a client,
var p1 = $.Deferred();
// client gets a promise for a future result
function get() {
return p1.promise();
}
At some time in the future, something else delivers the result that p1 should ultimately resolve to as either a value, or another promise:
// at some time in the future, something else completes p1 with either a value:
function resolveWithValue(val) {
p1.resolve(val);
}
// .. or with a promise
function resolveWithPromise(promise) {
// ... in which case we want p1 to resolve/reject/wait based on the promise arg:
// 1st try - doesn't work - p1.done() yields a promise, not the promise's value;
p1.resolve(promise);
// 2nd try - this works, but-- is there a better syntax?
promise
.done(function(v) { p1.resolve(v); })
.fail(function() { p1.reject(); });
}
My question is, is there a better syntax for that last line ('2nd try')? I believe other promise libs allow chaining like in '1st try' but I need $.Deferred() here.
I'm not looking for advice on how to restructure the code to avoid the chaining, I can't change it (nor can I share it, thus the contrived example).
Chaining Deferreds
If you want to treat p1 as a delegate of p2, connect them like so:
p2.then(p1.resolve, p1.reject, p1.notify)
Then, for example, if you call p2.resolve(x), it will call p1.resolve(x).
Why would you do this?
One concrete example: calling $.get() from inside a setTimeout callback, inside a helper function:
// Sends a GET request to `url` after `delayMs`.
// Returns a jQuery promise.
function startDelayedRequest(url, delayMs) {
var p1 = new $.Deferred();
setTimeout(function() {
var p2 = $.get(url);
p2.then(p1.resolve, p1.reject, p1.notify);
}, delayMs);
return p1;
}
Related
When I call this.requestUpdate() from within attributeChangedCallback(...) after I changed a classMap the render function is not called.
When I call it with a timeout it does seem to work. Is this the way to do it or is this a bug?
attributeChangedCallback(name: string, oldVal: AttributeType, newVal: AttributeType) {
super.attributeChangedCallback(name, oldVal, newVal);
...
this.myClassMap = {
...this.myClassMap,
foo: newValueBasedOnChangedProperty,
}
// this doesn't seem to do anything
this.requestUpdate();
// this does trigger a re-render
setTimeout(() => this.requestUpdate(), 0);
}
What also seems to work is waiting for the updateComplete promise using this:
this.updateComplete.then(
() => this.requestUpdate()
);
But it still feels like I'm putting the cart before the horse.
The behaviour I described above seems to be related to property changing in combination with reflection. See this issue on the LitElement GitHub repo for more info.
You should use await element.updateComplete.then(() => this.requestUpdate());
I want to pass a local variable from one function to another and I have tried some solutions but they didn't work because I have a click function, I need to put the variable first of all and I don't how to do it, also I declared the variable outside the function but if I use it outside of all the functions it doesn't has all its values or inside the function resaltar nothing appears, any help is welcome
let children=$('div[class^="fila"], div[class^="pieceRow"]' ).children()
var clase
$(children).each(function getClass(){
clase=$(this).attr('class')
$(clase).on('click', function resaltar(){
if (clase==clase) {
$(this).addClass('shadow')
}
})
})
this is the html code https://jsfiddle.net/qb5fwcus/
Please try this code :
let children = $('div[class^="fila"], div[class^="pieceRow"]' ).children();
$(children).on('click', function(){
var clase = $(this).attr('class');
resaltar(clase);
})
function resaltar(clase){
$('.shadow').removeClass('shadow');
$('.' + clase).addClass('shadow');
}
Explanation : You can not pass any value for the callback function for any event handler. Either it can be an anonymous function, or a function, not requiring any argument. However, you can achieve that, by making the callback function anonymous, and call any function from it. In this way, you can pass variables.
PS : Let me know if I got it wrong in any manner :)
Let's assume that you will be passing it to a pure JS function.
function myFunc() {
console.log("My function!");
}
In your 'click', you're calling the function ''resalter'', that you're also defining on the spot.
You want to call myFunc, so:
$(clase).on('click', myFunc())
Now, myFunc is not expecting a variable. Let's just pass a variable:
function myFunc(myVar) {
console.log("Passing a variable of type: " + typeof myVar);
}
Now, you're only expected to pass this var in the function you're calling. Given the previous example I gave, we have:
let x = 1; // our variable
$(clase).on('click', myFunc(x))
This way you're passing 'x' as a variable, of type integer. Use this code as inspiration to try and reach your goal. It is a bit hard to give a more exact answer, given that we don't know what variables have to be passed to what function and what the purpose is.
Good luck!
I was looking at the sample code for the tutorial at https://forge.autodesk.com/blog/custom-window-selection-forge-viewer-part-iii which is located at https://github.com/Autodesk-Forge/forge-rcdb.nodejs/blob/master/src/client/viewer.components/Viewer.Extensions.Dynamic/Viewing.Extension.SelectionWindow/Viewing.Extension.SelectionWindow.Tool.js as well as the documentation at https://developer.autodesk.com/en/docs/viewer/v2/reference/javascript/toolinterface/ --- Most of these functions are getting called properly in my tool such as handleSingleClick, handleMouseMove, handleKeyDown, and so on, but two of them are not getting hit -- handleButtonDown and handleButtonUp. I was using viewer version 3.3.x but I have updated to use 4.0.x thinking that that might help to resolve the problem, but the same issue occurs in both versions. Thanks for any help.
The following code block from theAutodesk.Viewing.ToolController#__invokeStack(), _toolStack stands for activated tools in the ToolController, the method stands for callback functions started with handle, i.e. handleSingleClick, handleMouseMove, handleKeyDown, handleButtonDown, handleButtonUp, etc.
for( var n = _toolStack.length; --n >= 0; )
{
var tool = _toolStack[n];
if( tool[method] && tool[method](arg1, arg2) )
{
return true;
}
}
Based on my experience, if there is a handle function such as handleButtonDown or handleButtonUp executed before your custom tools' and returned true, then your handles will never be called.
Fortunately, Forge Viewer (v3.2) starts invoking a priority mechanism for custom tools registered in ToolController. ToolController will use the priority number to sort the tools in it, and the priority number of each tool is 0 by default. You can override the priority to make your tools be hit before other tools like this way, to add a function getPriority() to return a number greater than 0:
this.getPriority = function() {
return 100;
};
I found out that when using ES6 and the class syntax, extending your tool from Autodesk.Viewing.ToolInterface will prevent the overrides to work properly, probably because it is not implemented using prototype in the viewer source code.
You can simply create a class and implement the methods that are of interest for your tool:
// KO: not working!
class MyTool extends Autodesk.Viewing.ToolInterface {
getName () {
return 'MyTool'
}
getNames () {
return ['MyTool']
}
handleButtonDown (event, button) {
return false
}
}
// OK
class MyTool {
getName () {
return 'MyTool'
}
getNames () {
return ['MyTool']
}
handleButtonDown (event, button) {
return false
}
}
I am new to knockout and sammy. I am implementing SPA using Sammy(router) and KnockOut(binding).
I have below code.
this.get('#/Page/:operation', function (context) {
this.partial('templates/Page1.html', { cache: false }).then(function (content) {
// the first argument to then is the content of the
// prev operation
$('#sammyDiv').html(content);
});
});
When I checked the console it's saying "You cannot apply bindings multiple times to the same element.(…)".
Am I doing anything wrong here?
What's the difference between Partial and Render?
Im guessing you are injecting new html into the parent which has already been bound. You should either be more specific about which divs you are binding too. I.E on apply bindings to the parent div of the html you injected, or clean and reapply bindings. I use both methods throughout my application.
if (isBound("my-div"))
ko.cleanNode(document.getElementById('my-div'));
ko.applyBindings(myModel, document.getElementById('my-div'));
Helper Function:
// Checks if Element has Already been Bound (Stops Errors Occuring if already bound as element can't be bound multiple times)
var isBound = function (id) {
if (document.getElementById(id) != null)
return !!ko.dataFor(document.getElementById(id));
else
return false;
};
I use this check before all my bindings as a safety net.
Thanks for the response and comments. Issue was with Sammy router.
this.get('#/Page/:operation', function (context) {
this.partial('templates/Page1.html', { cache: false }).then(function (content) {
// the first argument to then is the content of the
// prev operation
$('#sammyDiv').html(content);
});
});
changed to
this.get('#/Page/:operation', function (context) {
this.partial('templates/Page1.html', { cache: false });
});
It worked perfectly fine. Thanks again.
var s={};
s.WHEN={}
Why does this work:
s.WHEN.foo=5;
but this not:
s.WHEN['info']=function(){trace('do something');}
?
after I run both these lines my s.WHEN Object has only foo:5 and is missing info:function
I use this function to see from flash through the console in the browser...
var console:Object={
log:function(_){ExternalInterface.call("window.console.log",_);},
dir:function(_){ExternalInterface.call("window.console.dir",_);}
}
Then if I do (in flash):
console.log(s.WHEN);
I see:
Object
> foo: 5
> __proto__: Object
But if I do:
console.log(s.WHEN['info']);
I see:
function
Why is it there but not as part my s.WHEN object??
if you try
trace( console.log );
You will also see function because you are referencing a function and not a function call.
So use :
console.log( s.WHEN() );
But you will see nothing (well, you will have a trace in Flash console) because the function referenced by WHEN return nothing.
s.WHEN[ 'info' ] = function(){ return 'do something' };
console.log( s.WHEN() ); // <-- Note the bracket after WHEN
And it will work.
But as Gio said, you should use OOP and not anonymous Object/Function, it makes life easy and debug won't be a pain.