How do you implement in JS the pending execution of asynchronous tasks in the description of the class?

Good day to all.
The question is, how would you have solved the problem with the designer and asynchronous processes.
Example:
class Name {
 let self = this;
constructor(data){
this._init(data)
.then(data=>{
 self.init = data;
})
.catch(console.error);
}
 _init(data) { 
 return new Promise((resolve, reject) => {
 // artificially create a delay, mcleroy web request:
 setTimeout(resolve, 2000, data);
//resolve(data);
})
 run(data) {
 rerurn data / this.init.
}
run2(data){
 let self = this;
 return new Promise((resolve, reject) => {
 resolve(data / self.init);
})
}
}

In the example above we do when initializing an asynchronous task, assume that it will take some time (a request over http or something , not the point)
As an example:
let name = new Name(2);
console.log(name.run(6));
//or
name.run2(6).then(console.log).catch(console.error);

Expect to get 3, but can not get because of this.init may not be obtained and the constructor still works.
Who as with it struggles?
In my mind, and in practice implemented a crutch, a variable trigger, which symbolizes that the designer worked and if the trigger is not set, the delay is done, but I don't like this approach, can someone tell me a more elegant solution?

While I found the following solution:
1. Through the factory:
class Engine {
 constructor(data) {
 this.data = data;
}

 static makeEngine(pathToData) {
 return new Promise((resolve, reject) => {
 getData(pathToData).then(data => {
 resolve(new Engine(data))
}).catch(reject);
};
}
}

Plus I see that the object will be created only when you run the whole vermaland, minus the fact that the object is the result of promis and again either in the generator to work with him for convenience or async. Well or hard trolling all this stuff to write the basic code pochli taymouth.

2. Using a specific constructor , I liked the idea, but we need to test, plus to use a 7 node with harmony:
class Engine {

 constructor(path) {
 this.initialization = (async () => {
 this.resultOfAsyncOp = await doSomethingAsync(path)
})()
}

 async showPostsOnPage() {
 await this.initialization
 // actual body of the method
}

}
July 2nd 19 at 13:11
3 answers
July 2nd 19 at 13:13
Solution
Itself asked, itself answered....

welcome curious, but not devoid of issues, whether to do so. There is criticism of using the constructor to perform the initialization methods. But with asynchronous tasks, I thought it was acceptable.

Open to new ideas.

class Name {

 constructor(data) {
 console.log('start constructor');
 this.initialization = (async () => {
 this.init = await this._init(data)
})();
 console.log('constructor end');
}
_init(data){
 return new Promise((resolve, reject)=>{
console.log('_init');
 setTimeout(resolve, 2000, data);
});
}

 async run(data) {
 console.log('run start');
 await this.initialization;
 console.log('run end');
 return data for this.init;
}
}

let name = new Name(2);
name.run(6).then(console.log).catch(console.error);


Result:

>node --harmony test2
constructor start
_init
end constructor
run start
run end
3
July 2nd 19 at 13:15
Solution
A constructor should not call any methods with promises, just to add to the class type method getDb() with promis and call it by any other method, for example:
constructor() {
 this._existingDB = null;
}

 getDB() {
 return new Promise((resolve, reject) => {
 if(!this._existingDB) {
 mongoClient.connect(mongoConfig.host, (err, db) => {
 if(err) return reject(err);
 this._existingDB = db;
resolve(db);
});
 } else {
resolve(this._existingDB);
}
});
}

 getCollection(collectionName) {
 return new Promise((resolve, reject) => {
 this.getDB().then(db => resolve(db.collection(collectionName))).catch(reject);
});
 }

The result of the getDb() can be cached in a variable in the constructor, not to make extra query to the database every time.
Yes I agree, also an option, but in this situation, you need to check the cache values, and how to behave if it is not? throw to throw? Or be locked inside getCollection().then..... - sally_Carro commented on July 2nd 19 at 13:18
: I've expanded the code in the example. This is an example of my pet project. In production used, but it works without problems. - Aurore_Jenki commented on July 2nd 19 at 13:21
: And in your second version of the asynchronous operation in the constructor will be called every time. - Aurore_Jenki commented on July 2nd 19 at 13:24
after update the solution looks very elegant, thanks for the idea. - sally_Carro commented on July 2nd 19 at 13:27
however , the logic is that each method should perform only what he asked and not to cause within itself the initialization of other methods, this solution clearing the designer, makes each method of the class in the ninja code, but this is essentially the same as await this.initialization , probably not cool, you will need version or or.... - sally_Carro commented on July 2nd 19 at 13:30
the most interesting is that no asynchronous operation is called multiple times await this.initialization works as a condition to wait for execution if it has already been executed, re-execution will not be. Just checked. - sally_Carro commented on July 2nd 19 at 13:33
: I'm not saying that the methods should not call other methods. I just don't put it in writing "should not". I meant "not obliged", not "not allowed" ) - Aurore_Jenki commented on July 2nd 19 at 13:36
perform just such a funny piece of writing:
let name = new Name(2);
name.run(6).then(console.log).catch(console.error);
name.run(60).then(console.log).catch(console.error);
setTimeout(()=>{
name.run(12).then(console.log).catch(console.error);
name.run(24).then(console.log).catch(console.error);
name.run(36).then(console.log).catch(console.error);
name.run(48).then(console.log).catch(console.error);
},3000);

in the console _init fell out only 1 time, even taking into account that calls 6 and 60 both were waiting for initialization. - sally_Carro commented on July 2nd 19 at 13:39
: about the methods that you were not talking, methodology is recommended to adhere to the transparency code and are not recommended to prevent a situation when inside method of creating a table is unexpectedly added to the first 5 records, you know. By the way, the example that I dug with avicom can be rewritten as in a separate initialization method, and in the factory. I think he is a very curious behavior standard, I still think implicit. - sally_Carro commented on July 2nd 19 at 13:42
: this is a native async/await from the node or babel? - Aurore_Jenki commented on July 2nd 19 at 13:45
: native, ke 7 with --harmony - sally_Carro commented on July 2nd 19 at 13:48
and if people need to get updated data? - Aurore_Jenki commented on July 2nd 19 at 13:51
in _init is not processed reject. Most likely the query on it and falls, that's why he is not executed the second time. - Aurore_Jenki commented on July 2nd 19 at 13:54
: the idea is as soon as the await from the catch catches promis , it generates an exception, is the mind each async await in the try catch stuff, but for example, I did not. I think there is some solution, like that of promis works only 1 time or more it can't be. - sally_Carro commented on July 2nd 19 at 13:57
: > and if people need to get updated data?
this is not initialization , and a getter for this there is a little different, all should be solved. - sally_Carro commented on July 2nd 19 at 14:00
I delved into the question, so this.initialization essentially refers to the promise with its condition, as promis is an object, it is in memory exists in a single copy and at the start it looks like this: Promise { pending } and await seeing this as object waits for the completion. When the object of promis had done its job, the object keeps the state of the fulfilled or rejected, and the value that it received. In this state, promis more fulfilling itself will not. And accordingly await seeing these States has a ready value. In my example, if dumped to the console output of this promis Posel they Promise will be seen result { 2 }
. Hence, we can conclude that the call to await promiseName will either wait or return the value of promis. something like this, can certainly misinterpret the docks, but the direction of thought is correct. - sally_Carro commented on July 2nd 19 at 14:03
: Yes, it certainly is all interesting, but you have in _init every time creates a new Promise, the new promise, and this means that the old object of promis in memory it is irrelevant. - Aurore_Jenki commented on July 2nd 19 at 14:06
: you have way to class three properties starting at init, which significantly complicates code reading. I understand that it is sketched on the knee, but still hold at least some refactoring on the fly think you need. - Aurore_Jenki commented on July 2nd 19 at 14:09
: to the point, and this _init is called once in the constructor, this.initialization only link to this promis. - sally_Carro commented on July 2nd 19 at 14:12
: on account of variables with the name init Yes there is a joint, got carried away - sally_Carro commented on July 2nd 19 at 14:15
July 2nd 19 at 13:17
I think you did not understand my question. What is the function supposed to return a promise? What does it do? The class constructor is not a promis. - sally_Carro commented on July 2nd 19 at 13:20
I can rewrite run(data) { return new Promise ..... } to perform a name.run(6).then(console.log) and no one will give me the assurance that in this case I get results, because there is no guarantee that the constructor has executed a promis _init so clearly? - Aurore_Jenki commented on July 2nd 19 at 13:23
: I well understand your question, apparently you did not understand my answer. You are inside the constructor - porridge. Normal practice - the result of a delayed process to return in the form of Promis. Why your run method(data) does not return a promise ? - Aurore_Jenki commented on July 2nd 19 at 13:26
: Promis and promis that he may fail, or may not, consider this in your future architecture. - sally_Carro commented on July 2nd 19 at 13:29
OK rewrote the example as run2 I'm more interested in how to make a crutch, which will be responsible for the finish of the initialization (through the constructor). - sally_Carro commented on July 2nd 19 at 13:32
: and also added the timeout, which would init was clearly not made to call both run and run2 - sally_Carro commented on July 2nd 19 at 13:35
: Read books. Timeout and promis is an epic pee.... - Aurore_Jenki commented on July 2nd 19 at 13:38
: well, don't brake, think of it as a get request, and setTimeout emulates timeout of the response to the request, the feeling that you literally perceive this code.... - sally_Carro commented on July 2nd 19 at 13:41
live example, suppose we collect a class for working with the database designer zapisyvaet the task of creating tables, indexes (which are implemented as promises), then write the function of adding data to tables, so when you declare a new instance of the class we will get start of initialization, and if directly just start pisat BB these tables, we get a situation where the tables yet and fro Hello... - sally_Carro commented on July 2nd 19 at 13:44
: How about you read the link that I added in response, and then continue the conversation. It is better to read twice. You have a problem with the architecture. - Aurore_Jenki commented on July 2nd 19 at 13:47
: updatel have a question, there two implementations of what I am. If you have a third, say thank you for the example in Studio. Subtraction of articles about what promis is not necessary to me. I might as well reply Google, it's a waste of time and who response big, and the person who asked. - sally_Carro commented on July 2nd 19 at 13:50

Find more questions by tags Node.js