在节点中使用外部sdk时,我注意到我写了很多重复的代码。例如:
from functools import reduce
from operator import or_
def name_contains(words):
if words:
return reduce(or_, (Q(word_contains=word) for word in words))
else:
return Q()
我想简化和抽象,以使其更清洁并想到这一点:
async function one(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.one(function(err, req, res) {
if (err) {
return reject(err);
}
resolve(res);
});
});
}
async function two(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.two(function(err, req, res) {
if (err) {
console.log(err);
return reject(err);
}
resolve(res);
});
});
}
我在运行此错误时遇到错误,即async function runner(fn, params?): Promise<any> {
return new Promise(function(resolve, reject) {
const _CB = cb.bind({ resolve, reject });
if (params) {
return fn(params, _CB);
}
return fn(_CB);
});
}
const one = async (): Promise<any> => {
return runner(sdk.one);
};
const two = async (): Promise<any> => {
return runner(sdk.two);
};
。我相信,问题在于Javascript是按值传递的。因此,当我在runner中运行this.helper is not a function
并尝试在其父fn(_CB)
上引用函数时,它不知道this.helper
是什么,因为fn实际上只是一个复制块码。实际上,在我想到这一点之前,我尝试this
sdk函数,但是我得到了和我在这里一样的错误。
我想到了这个解决方法,但我想知道是否有更好的方法?
util.Promisify
答案 0 :(得分:0)
当sdk试图给你回电话时你是否正在失去范围?您可以使用箭头功能来保留这些调用的范围。它与旧版目标的中间_CB
变量的工作方式类似,但在最新的ECMAScript版本中,它是原生的。
async function one(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.one((err, req, res) => { // Scope preserving arrow function
if (err) {
return reject(err);
}
resolve(res);
});
});
}
async function two(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.two((err, req, res) => { // and here
if (err) {
console.log(err);
return reject(err);
}
resolve(res);
});
});
}
答案 1 :(得分:0)
嗯,你使用的是javascript,这种语言几乎可以让你做任何事情。您可以动态调用函数
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.ss.util.PropertyTemplate;
import java.util.Map;
import java.util.HashMap;
public class CreateExcelCellStyles {
public static CellStyle getPreferredCellStyle(Cell cell) {
// a method to get the preferred cell style for a cell
// this is either the already applied cell style
// or if that not present, then the row style (default cell style for this row)
// or if that not present, then the column style (default cell style for this column)
CellStyle cellStyle = cell.getCellStyle();
if (cellStyle.getIndex() == 0) cellStyle = cell.getRow().getRowStyle();
if (cellStyle == null) cellStyle = cell.getSheet().getColumnStyle(cell.getColumnIndex());
if (cellStyle == null) cellStyle = cell.getCellStyle();
return cellStyle;
}
public static void main(String[] args) throws Exception {
//the data
Object[][] data = new Object[][]{
{null, "Returns", "Benchmark 1", null, null, null, "Benchmark 2", null, null, null, "Benchmark 3", null, null, null},
{null, null, "PME Plus", null, null, "Direct", "PME Plus", null, null, "Direct", "PME Plus", null, null, "Direct"},
{null, null, "PME IRR", "IRR", "KS PME", "Alpha", "PME IRR", "IRR", "KS PME", "Alpha", "PME IRR", "IRR", "KS PME", "Alpha"},
{"1 Year", .17, .162, .162, 1.01, .007, .191, .191, .99, -.018, .192, .192, .99, -.018},
{"3 Year", null, null, null, null, null, null, null, null, null, null, null, null, null},
{"5 Year", null, null, null, null, null, null, null, null, null, null, null, null, null},
{"10 Year", null, null, null, null, null, null, null, null, null, null, null, null, null},
{"20 Year", .103, .051, .059, 1.17, .048, .071, .074, 1.11, .03, .062, .066, 1.14, .037},
{"Since Inception", .109, .062, .066, 1.15, .041, .079, .08, 1.10, .027, .073, .074, 1.12, .031},
};
//we need PropertyTemplate later
PropertyTemplate propertyTemplate = new PropertyTemplate();
//we need properties map for cell styles later
Map<String, Object> properties;
//creating workbook
Workbook workbook = new XSSFWorkbook();
//we need DataFormat later
DataFormat format = workbook.createDataFormat();
//creating default font
Font defaultFont = workbook.createFont();
defaultFont.setFontName("Calibri");
defaultFont.setFontHeightInPoints((short)12);
//we need font in bold and white for headings
Font defaultFontWhite = workbook.createFont();
defaultFontWhite.setFontName("Calibri");
defaultFontWhite.setFontHeightInPoints((short)12);
defaultFontWhite.setBold(true);
defaultFontWhite.setColor(IndexedColors.WHITE.getIndex());
//creating default cell style having default font
CellStyle defaultCellStyle = workbook.createCellStyle();
defaultCellStyle.setFont(defaultFont);
//we need percent style for numbers later
CellStyle percent = workbook.createCellStyle();
percent.cloneStyleFrom(defaultCellStyle);
percent.setDataFormat(format.getFormat("0.0%"));
percent.setAlignment(HorizontalAlignment.CENTER);
//we need user defined number style having unit "x" for numbers later
CellStyle doubleX = workbook.createCellStyle();
doubleX.cloneStyleFrom(defaultCellStyle);
doubleX.setDataFormat(format.getFormat("0.00\\x"));
doubleX.setAlignment(HorizontalAlignment.CENTER);
//creating sheet
Sheet sheet = workbook.createSheet();
//set default column styles
sheet.setDefaultColumnStyle(0, defaultCellStyle); //first column A = default
for (int c = 1; c < 14; c++) sheet.setDefaultColumnStyle(c, percent); //columns B to N = percent; some will be overridden later
sheet.setDefaultColumnStyle(4, doubleX); //column E = user defined number style having unit "x"
sheet.setDefaultColumnStyle(8, doubleX); //column I = user defined number style having unit "x"
sheet.setDefaultColumnStyle(12, doubleX); //column M = user defined number style having unit "x"
//put data in sheet
int r = 0;
for (Object[] rowdata : data) {
Row row = sheet.createRow(r++);
int c = 0;
for (Object celldata : rowdata) {
Cell cell = row.createCell(c++);
if (celldata instanceof String) cell.setCellValue((String)celldata);
else if (celldata instanceof Double) cell.setCellValue((Double)celldata);
cell.setCellStyle(getPreferredCellStyle(cell)); //get preferred cell style from column style
}
}
//add merged regions
sheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 5));
sheet.addMergedRegion(new CellRangeAddress(0, 0, 6, 9));
sheet.addMergedRegion(new CellRangeAddress(0, 0, 10, 13));
sheet.addMergedRegion(new CellRangeAddress(1, 1, 2, 4));
sheet.addMergedRegion(new CellRangeAddress(1, 1, 6, 8));
sheet.addMergedRegion(new CellRangeAddress(1, 1, 10, 12));
sheet.addMergedRegion(new CellRangeAddress(0, 2, 0, 0));
CellUtil.setVerticalAlignment(CellUtil.getCell(CellUtil.getRow(0, sheet), 0), VerticalAlignment.CENTER);
sheet.addMergedRegion(new CellRangeAddress(0, 2, 1, 1));
CellUtil.setVerticalAlignment(CellUtil.getCell(CellUtil.getRow(0, sheet), 1), VerticalAlignment.CENTER);
//styling the table headings (rows 1 to 3)
for (int rw = 0; rw < 3; rw++) {
Row row = sheet.getRow(rw);
for (int c = 0; c < 14; c++) {
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.GREY_50_PERCENT.getIndex()); //do using only IndexedColors for fills
//properties.put(CellUtil.FONT, defaultFontWhite.getIndex()); //up to apache poi 3.17
properties.put(CellUtil.FONT, defaultFontWhite.getIndexAsInt()); //since apache poi 4.0.0
CellUtil.setCellStyleProperties(CellUtil.getCell(row, c), properties); //do using CellUtil for **add** new properties to already applied cell styles
}
}
propertyTemplate.drawBorders(new CellRangeAddress(0, 2, 0, 13), BorderStyle.MEDIUM, BorderExtent.ALL); //since we have merged regions we can simply drawing all borders here
//styling the table body (rows 4 to 9)
for (int rw = 3; rw < 9; rw++) {
Row row = sheet.getRow(rw);
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.LEMON_CHIFFON.getIndex());
CellUtil.setCellStyleProperties(CellUtil.getCell(row, 0), properties); //column A
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.PALE_BLUE.getIndex());
CellUtil.setCellStyleProperties(CellUtil.getCell(row, 1), properties); //column B
for (int c = 2; c < 6; c++) {
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.LIGHT_GREEN.getIndex());
CellUtil.setCellStyleProperties(CellUtil.getCell(row, c), properties); //columns C:F
}
for (int c = 6; c < 10; c++) {
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.LIGHT_ORANGE.getIndex());
CellUtil.setCellStyleProperties(CellUtil.getCell(row, c), properties); //columns G:J
}
for (int c = 10; c < 14; c++) {
properties = new HashMap<String, Object>();
properties.put(CellUtil.FILL_PATTERN, FillPatternType.SOLID_FOREGROUND);
properties.put(CellUtil.FILL_FOREGROUND_COLOR, IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
CellUtil.setCellStyleProperties(CellUtil.getCell(row, c), properties); //columns K:N
}
}
propertyTemplate.drawBorders(new CellRangeAddress(3, 8, 0, 0), BorderStyle.MEDIUM, BorderExtent.OUTSIDE); //outside border around A4:A9
propertyTemplate.drawBorders(new CellRangeAddress(3, 8, 1, 1), BorderStyle.MEDIUM, BorderExtent.OUTSIDE); //outside border around B4:B9
propertyTemplate.drawBorders(new CellRangeAddress(3, 8, 2, 5), BorderStyle.MEDIUM, BorderExtent.OUTSIDE); //outside border around C4:F9
propertyTemplate.drawBorders(new CellRangeAddress(3, 8, 6, 9), BorderStyle.MEDIUM, BorderExtent.OUTSIDE); //outside border around G4:J9
propertyTemplate.drawBorders(new CellRangeAddress(3, 8, 10, 13), BorderStyle.MEDIUM, BorderExtent.OUTSIDE); //outside border around K4:N9
//apply the PropertyTemplate borders
propertyTemplate.applyBorders(sheet);
//resizing the columns A:N
for (int c = 0; c < 14; c++) sheet.autoSizeColumn(c, true);
//writing the result
FileOutputStream out = new FileOutputStream("CreateExcelCellStyles.xlsx");
workbook.write(out);
out.close();
workbook.close();
}
}
并将其称为async function promisify(fnName): Promise<any> {
return new Promise((resolve, reject) => {
sdk[fnName](function(err, req, res) {
if (err) {
return reject(err);
}
resolve(res);
});
});
}
如果您使用当前的LTS 8.X节点版本或更大版本,则可以使用https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original
如果没有,您可以尝试使用bluebird方法:http://bluebirdjs.com/docs/api/promise.promisify.html
答案 2 :(得分:0)
实际上,您的runner
函数名称错误,应重命名为promisify
。因为正如我所见,您希望将回调样式函数转换为承诺版本。
检查Node.js 8中的util.promisify(original)
方法
https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original
答案 3 :(得分:0)
我不知道这是否是'正确'或最佳方式,但这是我最终做的事情,以防任何人遇到类似的问题:
const sdk = new Sdk({ creds });
function runner(fn): Promise<any> {
return new Promise((resolve, reject) => {
const cb = (err, req, res) => err ? reject(err) : resolve(res);
return fn(cb);
});
}
function list(): Promise<any> {
return runner(sdk.namespace1.list.bind(sdk.namespace1));
}
function create(param1: string, param2: string): Promise<any> {
return runner(sdk.namespace2.create.bind(sdk.namespace2, {
object: { param1, param2 },
}));
}
它可能与util.promisify
非常类似,只是这个sdk很奇怪。可能最终会将它重命名为promise-y。