I'm working on a project in Node.js that uses user certificates. I need to generate them synchronously, in a blocking manner, but the library I use (pem) has only asynchronous functions (callbacks). I tried multiple ways to tackle the problem, but none of my tries have been successful. My code looks like this:
function KeyObject(CN, serverKey, days = 365) { // key object
if (typeof CN !== 'string' ||
typeof days !== 'number' ||
typeof serverKey !== 'object') {
throw TypeError;
}
this.CN = CN;
this.days = days;
const _this = this;
async function generatePrivate() {
var p = new Promise((resolve, reject) => {
pem.createPrivateKey((err, obj) => {
if (err) reject(err);
_this.private = obj.key;
resolve();
});
});
await p;
}
async function generateCert(serviceKey) {
if (typeof serviceKey !== 'object') {
throw TypeError;
}
var p = new Promise((resolve, reject) => {
pem.createCertificate({
commonName: _this.CN,
days: _this.days,
serviceKey: serviceKey.private
}, (err, obj) => {
if (err) reject(err);
_this.cert = obj.certificate;
resolve();
});
});
await p;
}
// init the keys
generatePrivate();
generateCert(serverKey);
}
This code goes straight through and doesn't wait for the functions to complete. What should I do?
Thanks in advance.
You should just return the Promise from each of those functions - no need to await or make them async. You also can't have an async constructor, perhaps adding an async factory would work.
Related
NB: this javascript uses the openui5 libraries
attachOnceAsync: function(binding, callback) {
var args = [...arguments]
args.splice(0, 2)
return new Promise((resolve, reject) => {
var dataReceived = function(oEvent) {
if (typeof callback == 'function') {
if (callback.constructor.name === "AsyncFunction") {
callback(oEvent, ...args).then(() =>
resolve(oEvent)
).catch((err) => {
reject(err)
})
} else {
try {
callback(oEvent, ...args);
resolve(oEvent)
} catch (err) {
reject(err)
}
}
} else {
resolve(oEvent, ...args);
}
}
binding.attachEventOnce("dataReceived", dataReceived);
})
}
There aren't any Promise versions of events like "dataReceived" so this is my attempt to wrap one up.
In this case, callback is undefined (it shouldn't be, but that's a different issue). The line resolve(oEvent, ...args); is hit instead, only it never returns out of the await!
I changed that line to just resolve(oEvent) but still no joy.
Any ideas what I'm doing wrong?
Thanks
PS: I'll keep an eye on this question so I can offer any extra info required
here's how I call it:
handleAsync: async function(controller) {
/* Lots of setup */
var response = await fetch(/*redacted*/ )
if (response.status === 400) {
console.log(await response.json());
throw new BadRequestException();
}
if (response.status === 204){
/* more setup */
context = oPanel.getBindingContext("odata");
var updatePurchaseOrderDocTotalFunc = this.updatePurchaseOrderDocTotal
var callback = async function() {
var docTotalUpdate = await updatePurchaseOrderDocTotalFunc(oView, context, oModel, agreedPrice);
if (docTotalUpdate && docTotalUpdate.status === 204) {
await context.refresh();
}
}
//-- HERE --
await AsyncBinding.attachOnceAsync(binding,callback)
await context.refresh();
}
return true;
}
Ok - The answer was staring at me.
Sorry I wasn't able to provide a working snippet but the ui5 scripts are quite extensive.
I have several other functions that return a Promise so I can use the await/async approach, but with this one I forgot to include the action that causes the event to fire.
I renamed the function to show what it now does, and included the action that causes the event to fire:
RefreshAsync : function(context,binding, callback){
var args = [...arguments]
args.splice(0,2)
return new Promise((resolve,reject)=>{
var dataReceived = function(oEvent){
if(typeof callback == 'function' ){
if(callback.constructor.name==="AsyncFunction"){
callback(oEvent, ...args).then(()=>{
resolve(oEvent)
}).catch((err)=>{
reject(err)
})
}else{
try{
callback(oEvent, ...args);
resolve(oEvent)
}catch(err){
reject(err)
}
}
}else{
resolve([oEvent, ..args])
}
}
binding.attachEventOnce("dataReceived", dataReceived);
//This is the action I missed
context.Refresh()
})
},
I'm developing a Google Chrome extension which collects data from two servers and sends it to another service. I don't understand how to make it asynchronous. The requests seem to work fine.
I searched Google for some explanations but just found some basic tutorials with timeouts. Also, the Product-Server accepts the Ajax request, the Deal-Server doesn't (CORS Error). So I used XMLHttpRequest.
document.addEventListener("DOMContentLoaded", function () {
var createButton = document.getElementById("createButton");
createButton.addEventListener("click", function () {
getProducts();
getDeals();
}, false)
function getProducts() {
var list = [];
chrome.tabs.getSelected(null, function (tab) {
var Url = parseDealIdToUrl(tab.url)
$.get(Url, function (data, status) {
const jsonData = JSON.parse(JSON.stringify(data))
const productArray = jsonData.data
productArray.forEach(product => {
productList.push(new Product(product.id, product.deal_id, product.product_id, product.name, product.item_price, product.quantity, product.duration, product.discount_percentage, product.currency, product.sum, product.sum_formatted))
});
})
});
}
function getDeals(maxPages = 1, currentPage = 1, akquises = []) {
var akquiseList = akquises;
if (currentPage <= maxPages) {
var Url = dealUrl + currentPage
var xhr = new XMLHttpRequest();
xhr.open("GET", Url, true);
xhr.setRequestHeader("Authorization", "Token token=")
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
const akquiseArray = JSON.parse(xhr.responseText);
akquiseArray.forEach(akquise => {
akquiseList.push(new Akquise(akquise.name, akquise.id))
});
getDeals(handlePagination(xhr.getResponseHeader("Link")), currentPage + 1, akquiseList)
}
}
xhr.send();
}
}
}, false)
I want to call both functions and wait till both Lists are filled, then send the Data to the Service. Any idea would help me!
I'm not quite sure what you mean by "make it asynchronous." As wOxxOm said, XMLHttpRequest is an asynchronous method. Do you mean you're not sure how to combine the results of multiple asynchronous operations? For the sake of this answer I'll assume that's the case.
Basic Asynchronicity
In order to break down how asynchronous functions work, let's look at a simplified example of your code. Below we have a main function that calls 2 different asynchronous functions. When you run this block you'll get a DONE message logged to the console, Async 1 complete logged after 1 second, and Async 2 complete logged 1 more second later.
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
(function main() {
doAsync1();
doAsync2();
console.log('DONE');
})()
function doAsync1() {
setTimeout(() => {
console.log('Async 1 complete');
}, 1000);
}
function doAsync2() {
setTimeout(() => {
console.log('Async 2 complete');
}, 2000)
}
The reason DONE is logged before the other statements is because doAsync1 and doAsync2 are asynchronous – it take a couple seconds for them to complete their work. When you call doAsync1() in main, the JS engine will step into the doAsync1 function and start executing lines. The first line is a setTimeout call. This function takes its first argument and schedules it for execution 1000 milliseconds later.
At this point the JS engine has done everything it can in doAsync1, so it steps out of that function and calls the next line, doAsync2. Again, doAsync2 schedules its callback for future execution and returns.
Next, the engine will execute the console.log line which makes DONE appear in the console.
1000 ms later, the callback scheduled by doAsync1 will run execute and log Async 1 complete to the console. Another 1000 ms later the callback scheduled by doAsync2 will log Async 2 complete.
Basic Callbacks
Now let's say doAsync1 and doAsync2 generate some data we want to use in main once both of complete. In JS, we traditionally use callbacks to get notified when some operation we're interested in completes.
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
function doAsync1(callback) {
setTimeout(() => {
console.log('Async 1 started');
const data = "Async 1 payload";
callback(data);
}, 1000);
}
function doAsync2(callback) {
setTimeout(() => {
console.log('Async 2 started');
const data = "Async 2 payload";
callback(data);
}, 2000);
}
(function main() {
const response = {};
doAsync1(handleAsync1);
doAsync2(handleAsync2);
function handleAsync1(data) {
response.async1 = data;
handleComplete();
}
function handleAsync2(data) {
response.async2 = data;
handleComplete();
}
function handleComplete() {
if (response.hasOwnProperty('async1') && response.hasOwnProperty('async2')) {
console.log('DONE', response);
}
}
})();
Promises
While this does the job, it's a bit verbose. Promises are an abstraction of one-time callbacks that makes it easier to chain blocks of work together.
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
// Promisified version of setTimeout
function timeout(duration) {
return new Promise(resolve => {
setTimeout(resolve, duration);
});
}
function doAsync1(callback) {
return timeout(1000).then(() => {
console.log('Async 1 started');
const data = "Async 1 payload";
return data;
});
}
function doAsync2(callback) {
return timeout(2000).then(() => {
console.log('Async 2 started');
const data = "Async 2 payload";
return data;
});
}
(function main() {
// Starts both doAsync1 and doAsync2 at the same time. Once both complete, the
// promise will resolve with both response values.
Promise.all([
doAsync1(),
doAsync2()
]).then(response => {
console.log('DONE', response[0], response[1]);
});
})();
Async/Await
With ES2016 we gained 2 new keywords: async and await. These keywords are essentially syntactic sugar that make it a little easier to work with promises in JavaScript. For demo purposes, let's take a look at our Promises example converted to async/await.
// Copyright 2019 Google LLC.
// SPDX-License-Identifier: Apache-2.0
function timeout(duration) {
return new Promise(resolve => {
setTimeout(resolve, duration);
});
}
async function doAsync1(callback) {
await timeout(1000);
console.log('Async 1 started');
const data = "Async 1 payload";
return data;
}
async function doAsync1(callback) {
await timeout(2000);
console.log('Async 2 started');
const data = "Async 2 payload";
return data;
}
(async function main() {
const response = await Promise.all([
doAsync1(),
doAsync2()
]);
console.log('DONE', response[0], response[1]);
})();
For a much deeper dive into async functions, check out Async functions - making promises friendly by Jake Archibald.
Use the following code snippet to add async/await functions to chrome extension.
Usage: put the following code snippet to the beginning of both your content script and background script.
/**
* Usage:
* let cookies = await asyncfy(chrome.cookies.getAll)({ url })
* let tabs = await asyncfy(chrome.tabs.query)({active: true, currentWindow: true})
*
* #param fn A function that takes one or more parameters, and the last parameter is a callback which has one or more parameter. The simplest one is chrome.management.getSelf
* #returns {function(...[*]): Promise<any>} Return one value if the results array has only one element, else return the whole results array
*/
let asyncfy = fn => (...args) => {
return new Promise((resolve, reject) => {
fn(...args, (...results) => {
let { lastError } = chrome.runtime
if (typeof lastError !== 'undefined') reject(lastError);
else results.length == 1 ? resolve(results[0]) : resolve(results);
});
});
}
let isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
// provide async method to all methods which have one callback.
let handler = {
get: function(target, prop, receiver) {
let value = target[prop]
let type = typeof value
if(type !== 'undefined') { // including null, false
if( type === 'function') return value.bind(target); // correct the this for the functions, since we've substituted the original object to the proxy object
return value;
}
if(prop.endsWith('Async')){
let key = prop.replace(/Async$/, '')
let method=target[key]
let asyncMethod = asyncfy(method.bind(target));
return asyncMethod;
}
}
}
// proxy every leaf object
let asyncfyObj = handler => obj => Object.getOwnPropertyNames(obj)
.filter(prop => isObject(obj[prop]))
.forEach(prop => obj[prop] = new Proxy(obj[prop], handler))
// intercept the getters of all object in chrome member
asyncfyObj(handler)(chrome)
asyncfyObj(handler)(chrome.storage)
// console.log(`active tab: ${JSON.stringify(await getActiveTabAsync())}`)
let getActiveTabAsync = async () => {
let tabs = await chrome.tabs.queryAsync({active: true, currentWindow: true});
return (tabs && tabs.length > 0) ? tabs[0] : null;
}
// chrome.storage.local.set({ foo: 'bar' });
// console.log(`foo: ${await getLocalStorageAsync('foo')}`)
let getLocalStorageAsync = async key => ( await chrome.storage.local.getAsync([key]) ) [key];
Testing: put the following snippet in your background script and make sure related permissions have been added to the manifest.json.
(async () => {
console.log(cookies: ${JSON.stringify(await asyncfy(chrome.cookies.getAll)({ url: 'https://www.stackoverflow.com/' }))})
console.log(active tab: ${JSON.stringify(await getActiveTabAsync())})
chrome.storage.local.set({ 'foo': 'bar'});
console.log(storage: ${await getLocalStorageAsync('foo')})
console.log(extension install type: ${( await chrome.management.getSelfAsync() )['installType']})
} )()
my gist
I have a asynchronous code which I want to run synchronously in one of my node js script, But this doesn't wait for the code block to complete and resolves the empty object -
new Promise((resolve, reject) => {
if (object.email !== undefined) {
for (let i = 0; i <= object.email.length; i++) {
let emailObject = object.email[i]
if (emailObject !== undefined) {
this.isEmailUnsubscribed(emailObject, options).then(result => {
console.log('>> isEmailUnsubscribed result in send email notification: ' + result)
if (!result) {
emailObjects.push(emailObject.EmailID)
}
})
}
}
console.log('emailObjects')
console.log(emailObjects)
resolve(emailObjects)
}
}).then(emailObjects => {
object.email = emailObjects
console.log('Email Objects from rules.evaluate')
console.log(emailObjects) // At this point my object is always empty.
this.sendEmailToSelectedUsers(object, options)
})
This is because your loop is generating new promises that are resolved asycnoursly, use Promise.all when you need to run multiple promises:
For example:
if (object.email !== undefined) {
return Promise.all(object.email.map( emailObject => {
if(emailObject){
return this.isEmailUnsubscribed(emailObject, options)
}else{
return Promise.resolve()
}
} ))
.then(emailObjects => {
object.email = emailObjects
console.log('Email Objects from rules.evaluate')
console.log(emailObjects) // At this point my object is always empty.
this.sendEmailToSelectedUsers(object, options)
})
}
I'm using for loop to iterate over an array of elements and to call the same function with different parameters inside the for loop. Here is my code:
exports.listTopSongs = function(query) {
return new Promise(function(resolve, reject) {
var str = query.split(","), category,
for(var i=0; i<str.length; i++) {
sampleFn(str[i], 'sample', resolve, reject);
}
});
};
function sampleFn(lang, cat, resolve, reject) {
client.on("error", function (err) {
console.log(err);
var err = new Error('Exception in redis client connection')
reject(err);
});
client.keys(lang, function (err, keys){
if (err) return console.log(err);
if(keys.length != 0) {
client.hgetall(keys, function (error, value) {
var objects = Object.keys(value);
result['title'] = lang;
result[cat] = [];
var x =0;
for(x; x<objects.length; x++) {
var val = objects[x];
User.findAll({attributes: ['X', 'Y', 'Z'],
where: {
A: val
}
}).then(data => {
if(data != null) {
//some actions with data and stored it seperately in a Json array
if(result[cat].length == objects.length) {
resolve(result);
}
} else {
console.log(""+cat+" is not avilable for this value "+data.dataValues['X']);
}
});
}
});
});
}
Here it won't wait for completion of first iteration. It just run asyncronously before completing first iteration function. I need to return the result as result:[{ 1, 2}, {3,4}]. but it runs seamlessly and returns empty or only one object before completing all. How to resolve it.
I used node-async-loop. But it uses next and i can't able to send my parameteres while using that package. Please help me
Async provides control flow methods allowing to do so.
Using async.each:
async.each(openFiles, function(file, callback) {
// Perform operation on file here.
console.log('Processing file ' + file);
if( file.length > 32 ) {
console.log('This file name is too long');
callback('File name too long');
} else {
// Do work to process file here
console.log('File processed');
callback();
}
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
If you don't want to use a library, you can code it yourself. It would also be very instructive. I took your issue and coded a dummy async loop :
function listTopSongs(query) {
return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls
const str = query.split(",") //str is const, and the other variable was not used anyway
for( let i = 0;i < str.length; i++) {
const planet = await sampleFn(str[i], 'sample', resolve, reject)
console.log(planet)
}
});
};
function sampleFn(a, b, c, d) {
return fetch(`https://swapi.co/api/planets/${a}/`)
.then(r => r.json())
.then(rjson => (a + " : " + rjson.name))
}
listTopSongs("1,2,3,4,5,6,7,8,9")
I used some dummy star wars API to fake a long promise but it should work with your sampleFn. Be careful, it is very, very slow if you have network call like the one in the example.
EDIT: I ran your code and I noticed there are a few mistakes: there is no resolve in your promise so it's not a thenable (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve see thenable )
Here is a fully working code. The nice part : no library needed, no dependencies.
//for node.js, use node-fetch :
//const fetch = require("node-fetch")
function listTopSongs(query) {
return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls
const str = query.split(",") //str is const, and the other variable was not used anyway
const planets = []
for (let i = 0; i < str.length; i++) {
const planet = await sampleFn(i + 1, str[i], resolve, reject)
planets[i] = planet
console.log(planet)
}
resolve(planets)
});
};
function sampleFn(a, b, c, d) {
return fetch(`https://swapi.co/api/planets/${a}/`)
.then(r => r.json())
.then(rjson => (a + b + " : " + rjson.name))
}
listTopSongs("a,b,c,d").then(planets => console.log(planets))
Since you are using promise, you can do something like this
exports.listTopSongs = function(query) {
return Promise.resolve(true).then(function(){
var str = query.split(",");
var promises = str.map(function(s){
return sampleFn(str[i], 'sample');
});
return Promise.all(promises);
}).then(function(results){
//whatever you want to do with the result
});
};
For this to work you have to change your sampleFn to not to depend on external resolve and reject functions. I don't see a reason using external resolve and reject. why just not use Promise.Resolve, Promise.Reject;
Inside a promise, I need to call and process an indeterminate number of asynch API responses after individually calling them either inside another promise, or after said promise, but before another so the order of execution is respected.
var promiseA = function() {
return new Promise(function(resolve, reject) {
// 1. Establish objects needed from one API endpoint
// 2. Call API endpoint for each object and parse
// 3. Only then continue to next promise
}
}
var finalPromise = function() {
return new Promise(function(resolve, reject) {
//
}
}
promiseA()
.then(finalPromise)
So inside promiseA, I find out how many objects I'll need to poll individually from an API. Each request is of course asynchronous. I need to make these calls and process the response before the final promise is called.
I am struggling to determine a pattern for this with promises, where I can dynamically create these promises and only allow the final promise to execute after the indeterminate and asynchronous have executed and processed. I've worked with other languages where this is possible, but I'm struggling to see it here with Promises.
Any help is appreciated.
I have changed the answer to incorporate the comments below. Since, you mentioned ES6 promises I shall stick to that. There are two basic types of callbacks that we might care about.
DOM load or other one time event callbacks (window.onload and so on)
Async method callback (AJAX call, setTimout and so on)
Since,
1.DOM load or other one time event
var p = new Promise(function(res, rej) {
window.onload = res();
};
2.Plain callback: these are callbacks that don't conform to a convention. e.g. setTimeout
var p = new Promise(function(res, rej){
setTimeout(function() {
//your business/view logic
success? res():rej(); //if successful resolve else reject
}, 2000);
});
In each of the above case the promise (var p) can be wrapped to be returned by a function.
var myAsyncMethod = function () {
var p = new ... // as mentioned in 1 or 2
return p;
}
Then the usage:
myAsyncMethod()
.then(function(){/* success-handler */})
.catch(function(/* failure-handler */));
Specific to your question you may have many such methods:
function baseAJAXCall (url) {
new Promise(functoin(rej, res) {
$.get(url, function(err, data){
if(err) {
rej();
}
else {
resolve(data);
}
});
}
};
function callAPIEndpoint(url) {
return baseAJAXCall(url);
}
function finalPromiseHandler () {
//your final business/view logic
}
//USAGE
callAPIEndpoint('/my-first-call')
.then(function(data){
var promiseArray = data.map(function(item){
return baseAJAXCall(item.url);
});
return Promise.all(promiseArray);
})
.then(finalPromiseHandler)
.catch(function(){
console.log('.error-message.');
});
Ref:
How do I convert an existing callback API to promises?.
http://www.datchley.name/es6-promises/
Links from comments below.
---OLD ANSWER: PLEASE OVERLOOK---
I am familiar with this library : https://github.com/kriskowal/q. And, you can do this using using the q.all and q.allSettled constructs. May be that is what you are looking for.
Normally, the pattern is to create a function that returns a promise.
function someAsyncFuncName1(url) {
var def = q.defer();
//async function
$.get(url, function(err, data){ //suppose
if(err){
def.reject();
}
else {
def.resolve(data); //pass the data to the .then() handler.
}
});
return def.promise;
}
function someAsyncFuncName2() {
var def = q.defer();
//async function
setTimeout(function(){ //suppose
//do something
if(good) {
def.resolve();
} else {
def.reject();
}
}, 1000); //arbitrary timeout of 1 second
return def.promise;
}
USAGE:
q.all([someAsyncFuncName1('/api-1'), someAsyncFuncName2()])
.then(function() {
//final handler
});
On a similar line of thought one can use q.allSettled() if you want to wait for all promises to return.
Hope this helps.
---EOF OLD ANSWER---
First of all, if async functions used in PromiseA don't return promises, you need to promisify them. You can do that with Promise constructor, but it's much better to use libraries, such as bluebird with their promisify methods.
Let's imagine, that we have two functions getUserIdsAsync and getUserAsync. The first on returns a list of user ids, getUserAsync returns an user data by userId. And you need to get a list of users by their ids. The code of PromiseA could look so:
var promiseA = function() {
return getUserIdsAsync()
.then(userIds => {
let ops = users.map(uid => getUserAsync(uid));
return Promise.all(ops);
});
}
The following snippet shows a solution without using any external library like bluebird. It follows the code snippet in your question (which seems to be more complicate than needed).
You have to collect all api promisses in an array. Then you can call Promise.all() to get a Promise for the end of all api promisses. Then you can do some final stuff, like parsing the result of each promise and continue afterwards.
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var apiEndpoint = function (name) {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve('API ' + name + ' job done'), 1000);
});
}
var promiseA = function() {
return new Promise( (resolve, reject) => {
const promisses = [];
for (var i=1; i < getRandomInt(3,6); i++) {
// 1. Establish objects needed from one API endpoint
promisses.push(apiEndpoint('This is number ' + i));
}
Promise.all(promisses).then( results => {
// do final stuff
for (const s of results) {
// 2. Call API endpoint for each object and parse
console.log(s);
}
// continue ...
// 3. Only then continue to next promise
resolve('now it is finished');
}).catch( err => reject(err) );
});
}
var finalPromise = function() {
return new Promise( (resolve, reject) => {
console.log('finalPromise');
resolve();
});
}
promiseA()
.then( () => finalPromise())
.catch(err => console.log(err) );
Please hold in mind that this solution is not easy to read. Using external libraries or reducing promisses can improve readability. Maybe you should take a look to the async/await pattern to get a much more better (readable) solution.
Here is a solution with async/await:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const apiEndpoint = function (name) {
return new Promise( (resolve, reject) => {
setTimeout(() => resolve('API ' + name + ' job done'), 1000);
});
}
async function promiseParallel () {
const promisses = [];
for (let i = 1; i < getRandomInt(3,6); i++) {
promisses.push(apiEndpoint('This is number ' + i));
}
for (const p of promisses) {
const x = await p;
console.log(x);
}
return ('everything is done');
}
promiseParallel().then( result => {
console.log(result);
}).catch( err => console.log(err) );
If you want call the promisses sequentially you can replace with:
async function promiseSequ () {
for (let i = 1; i < getRandomInt(3,6); i++) {
const x = await apiEndpoint('This is number ' + i);
console.log(x);
}
return ('everything is done');
}