I have written a util class, which is a wrapper around promise based vendor library. My application will call this class (within App & Actions) to perform certain operations.
I am currently dealing with a scenario where my code needs to know the return value of promise within the Util class before proceeding to the next step. How can I do that?
The following is the tree structure of my code:
├── index.html
├── package-lock.json
├── package.json
├── scripts
│ ├── vendor_script.min.js
├── src
│ ├── actions
│ │ └── index.js
│ ├── common
│ │ └── js
│ │ └── WrapperAroundVendorScript_Utils.js
│ ├── components
│ │ └── app.js
│ ├── index.js
│ └── reducers
│ └── index.js
├── style
│ └── style.css
├── webpack.config.js
├── yarn-error.log
└── yarn.lock
Here, vendor_script.min.js is a vendor supplied JS library that uses JS promises to perform various actions. I have written a util class (WrapperAroundVendorScript_Utils.js) to abstract out the implementation details of vendor library.
WrapperAroundVendorScript_Utils.js
let instance = null;
class VendorUtils {
constructor (){
const config = {
some: value,
}
this._vendor = typeof window !== 'undefined' && window.vendor ? window.vendor : require([PATH]);
this._vendor.config = config;
};
static getInstance() {
if(typeof instance == "undefined" || !instance){
instance = new VendorUtils();
}
return instance;
}
doSomething(param1, param2) {
this._vendor.domSomething(param1 + param2);
.then(retVal => {
return {retVal};
});
};
doSomethingElse(param1, param2) {
this._vendor.domSomethingElse(param1 + param2);
.then(retVal => {
return {retVal};
});
};
}
module.exports.VendorUtils = VendorUtils;
app.js
import React, { Component } from 'react';
import {VendorUtils} from '../common/js/VendorUtils';
export default class App extends Component {
clicked(){
let utilsInstance = VendorUtils.getInstance();
let x = utilsInstance.doSomething('a','b');
let y = utilsInstance.doSomethingElse(x,'a');
// call action with values received in previous steps
}
render() {
return (
<div>
<button type='button' onClick={this.clicked}>Click Me!</button>
<button type='button' onClick={this.clicked}>Click Me!</button>
<button type='button' onClick={this.clicked}>Click Me!</button>
</div>
);
}
}
PS: I need such synchronous behavior because there are multiple child/nested/sub components within the class that will be calling such common functions.
This is a perfect example of where you would want to use async
/ await
async clicked() {
const utilsInstance = VendorUtils.getInstance();
const x = await utilsInstance.doSomething('a','b');
const y = await utilsInstance.doSomethingElse(x,'a');
...
}
You can either execute the code you want to wait inside the then
clause of you promoise, or you could use the async / await
feature of Javascript.
A detailed guide with examples can be found here .
There are some problems with your doSomething functions:
doSomething(param1, param2) {
this._vendor.domSomething(param1 + param2);
.then(retVal => {
return {retVal};
});
};
Consider to change your do something functions a bit:
doSomething(param1, param2) {
// return the promise
return this._vendor.domSomething(param1 + param2)
// maybe you don't need this part at all if you want to get only the value instead of {retVal: value} object
.then(retVal => {
// if you do async operations here make sure you returned a new
// promise here instead of object, in that case you would need
// another .then block to process internal promise that you
// would create inside this .then block
return {retVal};
});
};
that way, inside your async "clicked" function you would be able to use await for returned promises:
async clicked() {
let utilsInstance = VendorUtils.getInstance();
// you can check what doSomething returns here - it would be a promise
let doSomethingPromise = utilsInstance.doSomething('a','b');
// await a previously saved promise to get a value
let x = await doSomethingPromise;
// obviously you still can await promise in one sentence
let y = await utilsInstance.doSomethingElse(x,'a');
// call action with values received in previous steps
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.