Javascript refactor oftenly called function - refactoring

I'm working with javascript for quite a long time, but it happens to me often that I come up with the following code:
function1 () {
// do stuff
...
end_function();
}
function2 () {
// do stuff
...
end_function();
}
function3 () {
// do stuff
...
end_function();
}
I know this is in conflict with the DRY principles, but unfortunately, I don't know what to do with it to remove the repetitions. Does anyone know the answer?

There is so many solutions.
One way is wrap function like "am not i am's" answer,
another is use higher-order function.
var end_function = function(callback){
callback.call();
// do some stuff
};
var stuff1 = function(){};
var stuff2 = function(){}:
end_function(stuff1);
end_function(stuff2);

It would be in conflict with DRY if you code the end_function directly into the other functions. Ultimately you do need some syntax to invoke the code that you abstracted into its own function.
If functions are grouped together into an Object, I suppose you could enumerate the properties of the object, and wrap each function, but that's probably only worth it you have many of these functions.
var funcs = {
function1 () {
// do stuff
},
function2 () {
// do stuff
},
function3 () {
// do stuff
}
};
Object.keys(funcs).forEach(function(key) {
var orig = funcs[key];
funcs[key] = function() {
orig.apply(this, arguments);
end_function();
};
});

Related

egui::TextEdit::singleline with macroquad - not able to edit text

Trying to experiment with egui and macroquad, but can't get elements enabled for edit.
From the standard example:
use macroquad::prelude::*;
#[macroquad::main("")]
async fn main() {
loop {
clear_background(BLACK);
egui_macroquad::ui(|egui_ctx| {
egui_macroquad::egui::Window::new("egui ❤ macroquad").show(egui_ctx, |ui| {
ui.colored_label(egui_macroquad::egui::Color32::WHITE, "Test");
ui.add(egui_macroquad::egui::TextEdit::singleline(&mut "ku").text_color(egui_macroquad::egui::Color32::RED));
});
});
egui_macroquad::draw();
next_frame().await
}
}
In Cargo.toml:
[dependencies]
macroquad = "0.3.25"
egui-macroquad = "0.12.0"
As result:
I see the TextEdit::singleline widget, but can't edit it.
Should I enable it somehow or something else?
Found the solution. Mutable "String" variable must be defined and used for TextEdit::singleline:
use macroquad::prelude::*;
#[macroquad::main("")]
async fn main() {
let mut kuku: String = "ku".to_string();
loop {
clear_background(BLACK);
egui_macroquad::ui(|egui_ctx| {
egui_macroquad::egui::Window::new("egui ❤ macroquad").show(egui_ctx, |ui| {
ui.colored_label(egui_macroquad::egui::Color32::WHITE, "Test");
ui.add(egui_macroquad::egui::TextEdit::singleline(&mut kuku).text_color(egui_macroquad::egui::Color32::RED));
});
});
egui_macroquad::draw();
next_frame().await
}
}
Now it works, because it takes the values from the widget and assign them to the variable "kuku".

How to unit test a cross-contract call using NEAR (AssemblyScript)?

I'm trying to follow this example on how to create a unit test for a cross-contract call.
I have a cross-contract call like this
// Class with cross-contract calls
export class CalculatorApi {
add(a: string, b: string): ContractPromise {
let args: AddArgs = { a, b };
let promise = ContractPromise.create(OTHER_CONTRACT, "addLongNumbers", args.encode(), 100000000000000);
return promise;
}
}
// function to unit test
export function calculate(a: string , b: string): void { // Need to return void according to current spec
let calculator = new CalculatorApi();
let promise = calculator.add(a, b);
promise.returnAsResult();
}
You may notice this function returns void, which is a bit confusing because the contract is returning a promise. This is because it's calling a function elsewhere and the compiler thinks it's void.
(In future releases this will be changed.)
And a test like this
// VS Code complains about the async word
it("add one digit", async function() {
const params = { a: "1", b: "99" };
const result = await contract.calculate(params);
expect(result).toBe("100");
});
However, the above test complains about the syntax with the following error:
An async function or method must return a 'Promise'. Make sure you
have a declaration for 'Promise' or include 'ES2015' in your '--lib'
option.ts(2697)
I'm not sure, but maybe it has something to do with my tsconfig.json file, which looks like this:
{
"extends": "../node_modules/assemblyscript/std/assembly.json",
"include": ["./**/*.ts"]
}
I tried to add the following, but it didn't work
"compilerOptions": {
"lib": ["es2020"]
}

How to create a Promise from the nested kotlin.js.Promise?

kotlin.js.Promise has function then with this declaration:
open fun <S> then(
onFulfilled: (T) -> S,
onRejected: (Throwable) -> S = definedExternally
): Promise<S>
I have two functions a() and b(). They both return a Promise<Int>. (They represent some requests to the server.) I need to combine them and create a new function like:
fun c(): Promise<Int> {
a().then({
b()
})
}
But it is not possible, because return type is Promise<Promise<Int>> and not Promise<Int>.
I think this is possible in Javascript. How can I chain promises in Kotlin?
you need an additional Promise for that, for example:
fun c(): Promise<Int> {
return Promise({ resolve, reject ->
a().then({
b().then(resolve, reject);
});
})
}
the code above also can simplified by using single-expression function as below:
fun c() = Promise({ resolve, reject ->
a().then({
b().then(resolve, reject);
});
});
fun c(): Promise<Int> {
return a().then ({
b().unsafeCast<Int>()
//Result of b is Promise<Int>, not Int, but then has bad type declaration
})
}

PromiseKit 3.0: chaining with loops

I'm using promisekit 3.0 to help chain alamofire callbacks in a clean way. The objective is to start with a network call, with a promise to return an array of urls.
Then, I'm looking to execute network calls on as many of those urls as needed to find the next link i'm looking for. As soon as this link is found, I can pass it to the next step.
This part is where I'm stuck.
I can pick an arbitrary index in the array that I know has what I want, but I can't figure out the looping to keep it going until the right information is returned.
I tried learning from this obj-c example, but i couldn't get it working in swift.
https://stackoverflow.com/a/30693077/1079379
He's a more tangible example of what i've done.
Network.sharedInstance.makeFirstPromise(.GET, url: NSURL(string: fullSourceLink)! )
.then { (idArray) -> Promise<AnyObject> in
let ids = idArray as! [String]
//how do i do that in swift? (from the example SO answer)
//PMKPromise *p = [PMKPromise promiseWithValue: nil]; // create empty promise
//only thing i could do was feed it the first value
var p:Promise<AnyObject> = Network.sharedInstance.makePromiseRequestHostLink(.POST, id: ids[0])
//var to hold my eventual promise value, doesn't really work unless i set it to something first
var goodValue:Promise<AnyObject>
for item in ids {
//use continue to offset the promise from before the loop started
continue
//hard part
p = p.then{ returnValue -> Promise<AnyObject> in
//need a way to check if what i get is what i wanted then we can break the loop and move on
if returnValue = "whatIwant" {
goodvalue = returnValue
break
//or else we try again with the next on the list
}else {
return Network.sharedInstance.makeLoopingPromise(.POST, id: item)
}
}
}
return goodValue
}.then { (finalLink) -> Void in
//do stuck with finalLink
}
Can someone show me how to structure this properly, please?
Is nesting promises like that anti-pattern to avoid? In that case, what is the best approach.
I have finally figured this out with a combination of your post and the link you posted. It works, but I'll be glad if anyone has input on a proper solution.
func download(arrayOfObjects: [Object]) -> Promise<AnyObject> {
// This stopped the compiler from complaining
var promise : Promise<AnyObject> = Promise<AnyObject>("emptyPromise")
for object in arrayOfObjects {
promise = promise.then { _ in
return Promise { fulfill, reject in
Service.getData(stuff: object.stuff completion: { success, data in
if success {
print("Got the data")
}
fulfill(successful)
})
}
}
}
return promise
}
The only thing I'm not doing is showing in this example is retaining the received data, but I'm assuming you can do that with the results array you have now.
The key to figuring out my particular issue was using the "when" function. It keeps going until all the calls you inputted are finished. The map makes it easier to look at (and think about in my head)
}.then { (idArray) -> Void in
when(idArray.map({Network.sharedInstance.makePromiseRequest(.POST, params: ["thing":$0])})).then{ link -> Promise<String> in
return Promise { fulfill, reject in
let stringLink:[String] = link as! [String]
for entry in stringLink {
if entry != "" {
fulfill(entry)
break
}
}
}
}.then {
}
}

Can I use classes with the javascript module pattern?

I have a bunch of "modules" which follow the "JavaScript Module Pattern" as described in this popular article. To my understanding these modules are a way to aggregate various bits of behavior into neat namespaces.
But what if I want to be able to create a unique object instance which accepts arguments? As it stands, I can't do that as all the data is shared/static. I want to be able to do this:
var foo = new Some.Namespace.Whatever.Foo(config);
I can't change the structure of the pattern as we've been using it for a while and it works very well. I just want to tweak it so I can throw some "classes" into it which work with non-static data.
Why not try this?
var MODULE = (function () {
var my = {};
my.SomeClass = SomeClass;
function SomeClass(six) {
this.six = six;
}
SomeClass.prototype.five = 5;
return my;
})();
When you call var obj = new MODULE.SomeClass(6) it will give you a new object. obj.five is shared between all instances of SomeClass because it is attached to the prototype. However, obj.six is specific to that instance, because it is attached to obj.
Alternatively, you may not need for your class to be inside a module. You could use a class to replace the module where appropriate, because both modules and classes in this case have some overlapping functionality.
This is probably overuse of the module pattern, but is this what you mean?:
var Some = (function() {
var util = { /* ... */ };
return {
Namespace: (function() {
return {
Whatever: (function() {
var Foo = function(config) {
this.foo = config.foo || "foo";
this.bar = config.bar || "bar";
};
var Bar = function() {};
Foo.prototype.toString = function() {
return this.foo + " " + this.bar;
};
return {
Foo: Foo,
Bar: Bar
}
}())
};
}())
};
}());
var foo = new Some.Namespace.Whatever.Foo({foo: "hello", bar: "world"});
foo.toString() // "hello world"

Resources