I have a program that accepts POST requests with a body that contains numbers. My program checks is the numbers in body are prime numbers or not. Everything is well the first time, but every time after that the program remembers the past POST requests a checks them as well.
how can I reset the request queue so my program will only check the newest POST request?
here is the code:
import { createServer } from "http";
import { parse } from "querystring";
import { url } from "inspector";
import { port } from "./config.js";
let body = "";
let checkNumber = true;
const PORT = process.env.PORT || port;
const server = createServer(async (req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/html");
const FORM_URLENCODED = "application/x-www-form-urlencoded";
const POST_PATH = "api/numbers/prime/validate";
const GET_PATH = "api/numbers/prime";
if (req.headers["content-type"] === FORM_URLENCODED) {
//console.log(req.method);
if (req.method === "POST") {
req.on("data", (chunk) => {
body += chunk.toString();
});
}
if (req.url === `/${POST_PATH}`) {
let re = parse(body);
await checkValuesInObject(re);
console.log(checkNumber);
res.end(`${checkNumber}`);
}
res.end();
});
server.listen(PORT, () => {
console.log(`listening on port ${PORT}`);
});
async function checkIfFirstNumber(number) {
if (number == 1) {
return false;
} else {
for (let i = 2; i < number - 1; i++) {
if (number % i === 0) {
return false;
}
}
return true;
}
}
async function checkValuesInObject(obj) {
const amount = Object.keys(obj);
for (let i = 0; i < amount.length; i++) {
let valueAmount = obj[Object.keys(obj)[i]];
for (let j = 0; j < valueAmount.length; j++) {
checkIfFirstNumber(valueAmount[j]).then((answer) => {
console.log(`answer: ${answer}`);
if (!answer) {
checkNumber = false;
}
});
}
}
checkNumber = true;
}
async function printPrime(number) {
let numbers = "";
for (let i = 2; i <= number; i++) {
const check = await checkIfFirstNumber(i);
if (check) {
numbers += i + " ";
}
}
return numbers;
}
Related
I am creating an API for listing trip data with image and pdf base url,
All things are working fine but I can not access the last result array data_to_send out of for loop.
app.js
app.get("/getChallanList/:userId/:role", (req, res) => {
const userData = req.params;
let site_source = "";
let site_destination = "";
var site_from_name = "";
const data_to_send = [];
if (userData.role == "D") {
db.select("trip", "*", `driver_id = '${req.params.userId}'`, (data) => {
for (let i = 0; i < data.data.length; i++) {
site_source = data.data[i].site_from;
site_destination = data.data[i].site_to;
db.select(
"site",
"*",
`id in ('${site_source}','${site_destination}')`,
(data_site) => {
data.data[i].site_from = data_site.data[0].name;
data.data[i].site_to = data_site.data[1].name;
if (data.data[i].truck_challan_pdf != "") {
data.data[i].truck_challan_pdf =
base_url + "truckchallan/" + data.data[i].truck_challan_pdf;
}
if (data.data[i].driver_challan_pdf != "") {
data.data[i].driver_challan_pdf =
base_url + "driverchallan/" + data.data[i].driver_challan_pdf;
}
if (data.data[i].preparer_img != "") {
data.data[i].preparer_img = base_url + data.data[i].preparer_img;
}
if (data.data[i].driver_img != "") {
data.data[i].driver_img = base_url + data.data[i].driver_img;
}
data_to_send.push(data.data);
// console.log(data_to_send); // working
}
);
}
console.log(data_to_send); // empty
});
}
}
db.select
let select = (table, column, condition, callback) => {
try {
let sql = "SELECT " + column + " FROM " + table + " WHERE " + condition;
conn.query(sql, (err, results) => {
if (err) {
let data = {
status: 0,
data: sql,
message: "Something went wrong!",
};
callback(data);
} else {
let data = {
status: 1,
data: results,
message: "Success",
};
callback(data);
}
});
} catch (err) {
let data = {
status: 0,
data: err,
message: "In catch",
};
callback(data);
}
};
async await
app.get("/getChallanList/:userId/:role", async (req, res) => {
const userData = req.params;
let site_source = "";
let site_destination = "";
var site_from_name = "";
const data_to_send = [];
if (userData.role == "D") {
await db.select(
"trip",
"*",
`driver_id = '${req.params.userId}'`,
async (data) => {
// const data_to_send_ = [];
for (let i = 0; i < data.data.length; i++) {
site_source = data.data[i].site_from;
site_destination = data.data[i].site_to;
await db.select(
"site",
"*",
`id in ('${site_source}','${site_destination}')`,
(data_site) => {
data.data[i].site_from = data_site.data[0].name;
data.data[i].site_to = data_site.data[1].name;
if (data.data[i].truck_challan_pdf != "") {
data.data[i].truck_challan_pdf =
base_url + "truckchallan/" + data.data[i].truck_challan_pdf;
}
if (data.data[i].driver_challan_pdf != "") {
data.data[i].driver_challan_pdf =
base_url + "driverchallan/" + data.data[i].driver_challan_pdf;
}
if (data.data[i].preparer_img != "") {
data.data[i].preparer_img =
base_url + data.data[i].preparer_img;
}
if (data.data[i].driver_img != "") {
data.data[i].driver_img = base_url + data.data[i].driver_img;
}
data_to_send.push(data.data);
// console.log(data_to_send); // working
}
);
// data_to_send_.push(data_to_send);
}
console.log(data_to_send); // empty
}
);
}
}
this is because of the asynchronous behavior of NodeJs, so you have to plan things accordingly i.e
console.log(1)
db.select(
"trip",
"*",
`driver_id = '${req.params.userId}'`,
async (data) => {
console.log(2)
})
console.log(3)
The output of the above code would be 1 then 3 and then 2 and this is how NodeJs works it does not wait for I/O calls i.e DB query in your case.
Please check how promises work in NodeJs for more details.
Here is how you can accomplish your task:
const challanList = (userData) => {
return new Promise((resolve, reject) => {
const data_to_send = [];
db.select("trip", "*", `driver_id = '${req.params.userId}'`, data => {
for (let i = 0; i < data.data.length; i++) {
const site_source = data.data[i].site_from;
const site_destination = data.data[i].site_to;
db.select("site", "*", `id in ('${site_source}','${site_destination}')`, data_site => {
data.data[i].site_from = data_site.data[0].name;
data.data[i].site_to = data_site.data[1].name;
if (data.data[i].truck_challan_pdf != "") {
data.data[i].truck_challan_pdf = base_url + "truckchallan/" + data.data[i].truck_challan_pdf;
}
if (data.data[i].driver_challan_pdf != "") {
data.data[i].driver_challan_pdf = base_url + "driverchallan/" + data.data[i].driver_challan_pdf;
}
if (data.data[i].preparer_img != "") {
data.data[i].preparer_img = base_url + data.data[i].preparer_img;
}
if (data.data[i].driver_img != "") {
data.data[i].driver_img = base_url + data.data[i].driver_img;
}
data_to_send.push(data.data);
// console.log(data_to_send); // working
});
}
resolve(data_to_send);
});
});
};
app.get("/getChallanList/:userId/:role", async (req, res) => {
const userData = req.params;
const challanListResult =await challanList(userData);
console.log(challanListResult);
resp.json(challanListResult);
});
Without knowing what database or ORM you are using it is difficult to answer, but my suspicion is that db.select is an asynchronous method, i.e. it is returning a Promise. If so, the second console log is still seeing the "old" data_to_send.
Try adding an await in front of the first db.select call. (Don't forget the async in front of the callback in second argument of app.get.
Your database is asynchronous so console.log(data_to_send) gets called before the query finished executing. Try adding async before (req, res) in line 1 then await before db.select.
This works for me
app.get("/getChallanList/:userId/:role", async (req, res) => {
const userData = req.params;
let site_source = "";
let site_destination = "";
var site_from_name = "";
const data_to_send = [];
if (userData.role == "D") {
const data = await db.query(
`SELECT * FROM trip WHERE driver_id = '${req.params.userId}'`
);
// console.log(data.length);
// const data_to_send_ = [];
for (let i = 0; i < data.length; i++) {
site_source = data[i].site_from;
site_destination = data[i].site_to;
// cons
const site_data = await db.query(
`SELECT * FROM site WHERE id in ('${site_source}','${site_destination}')`
);
// console.log(site_data);
db.select(
"site",
"*",
`id in ('${site_source}','${site_destination}')`,
(data_site) => {
data[i].site_from = data_site.data[0].name;
data[i].site_to = data_site.data[1].name;
if (data[i].truck_challan_pdf != "") {
data[i].truck_challan_pdf =
base_url + "truckchallan/" + data[i].truck_challan_pdf;
}
if (data[i].driver_challan_pdf != "") {
data[i].driver_challan_pdf =
base_url + "driverchallan/" + data[i].driver_challan_pdf;
}
if (data[i].preparer_img != "") {
data[i].preparer_img = base_url + data[i].preparer_img;
}
if (data[i].driver_img != "") {
data[i].driver_img = base_url + data[i].driver_img;
}
data_to_send.push(data);
// console.log(data.data);
// console.log(data_to_send); // working
}
);
// data_to_send_.push(data_to_send);
}
// console.log(data_to_send);
// console.log(data_to_send);
res.send({ success: 1, data: data, message: "" });
}
I wrote this small program to fetch data. This however is done async. Since I nonetheless need to use the function holeVertreter(kzl) as a function in another module, I'd like to get a return value which I can eventually pass on.
Excuse my spaghetti code (I usually prettify the code when I am done with my task ...).
Credentials are stored in a file and are therefore not found in this file.
I'd like to end up with "vertreter" as a return value.
Thank you in advance.
const node = require("deasync");
const DSB = require('dsbapi');
const tabletojson = require('tabletojson');
const https = require('https');
const cred = require("./vertrCred");
const dsb = new DSB(cred["dsb"]["user"], cred["dsb"]["passw"]); //Sanitized - no Credentials here
//Stackoverflow 2332811
String.prototype.capitalize = function(lower) {
return (lower ? this.toLowerCase() : this).replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
};
function holePlan(kuerzel) {
dsb.fetch()
.then(data => {
const timetables = DSB.findMethodInData('timetable', data);
const tiles = DSB.findMethodInData('tiles', data);
var tilesStr = JSON.stringify(tiles["data"][0]["url"]);
var url = JSON.parse(tilesStr);
https.get(url, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end',() => {
var tableasjson = tabletojson.convert(data);
var erstetab = tableasjson[0];
var zweitetab = tableasjson[1];
var drittetab = tableasjson[2];
var viertetab = tableasjson[3];
var fuenftetab = tableasjson[4];
var sechstetab = tableasjson[5];
var siebtetab = tableasjson[6];
var achtetab = tableasjson[7];
if (typeof kuerzel === "undefined")
{
var regenechse = '(Aaa|Aaa[A-Za-z?]|[A-Za-z?]Aaa)';
}
else {
var name = kuerzel.capitalize(true);
var regenechse = '('+name+'|'+name+'[A-Za-z?]|[A-Za-z?]'+name+')';
}
const regex = new RegExp(regenechse,'g');
var sammel = Object.assign(drittetab,fuenftetab);
var z= 0;
var vertreter = {}
var y = JSON.parse(JSON.stringify(sammel));
for (i=0;i<y.length;i++) {
if (typeof y[i].Vertreter =='undefined') {
}
else {
if(y[i].Vertreter.match(regex))
{
z += 1;
vertreter[z] = y[i];
}
}
}
if (z == 0) {
// console.log("Es gibt nichts zu vertreten");
}
else {
//console.log("Es werden "+z+" Stunden vertreten");
return (vertreter);
} ;
});
})
})
.catch(e => {
// An error occurred :(
console.log(e);
});
}
//Stackoverflow
function warte(promise) {
var done = 0;
var result = null;
promise.then(
function (value) {
done = 1;
result = value;
return (value);
},
function (reason) {
done = 1;
throw reason;
}
);
while (!done)
node.runLoopOnce();
return (result);
}
function holeVertretung(kzl) {
var aufgabe = new Promise((resolve,reject) => {
setTimeout(resolve,1000,holePlan(kzl));
});
var ergebnis = warte(aufgabe);
if (typeof ergebnis === "undefined") {
console.log("Mist");
}
else {
console.log(ergebnis);
}
return ergebnis;
}
holeVertretung("Aaa");
That's not the right way to work with promises. If you do such infinite loop, it beats the whole purpose of using promises. Instead, return value from the promise, and use async-await like this:
function warte(promise) {
var done = 0;
var result = null;
return promise.then(
...
}
async function holeVertretung(kzl) {
var aufgabe = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, holePlan(kzl));
});
var ergebnis = await warte(aufgabe);
...
If async-await does not work for some reason, use then clause:
warte(aufgabe).then(value => {
var ergebnis = value;
});
I have to write a json response in a column of tsv file how can I do that?
I am using the following code. Please find me a solution? I have to check it but its not working.
//npm init -y gen package.json file
var unProcessedItems = [];
var data = loadData('./Alabama_Pre_Final.tsv');
async function X(i) {
if (data[i] && data[i][7]) {
console.log(data[i][7]);
function address(address_details) {
request({
url: 'https://us-extract.api.smartystreets.com/?auth-id=xxx&auth-token=xxx',
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: address_details,
},
(error, response, body) => {
if (!error && response.statusCode == 200) {
var res = JSON.parse(body);
let objectArray = [];
if (res.addresses[0].verified) {
objectArray.push(res.addresses[0].api_output[0].delivery_line_1, res.addresses[0].api_output[0].last_line, res.addresses[0].api_output[0].delivery_point_barcode)
}
var address_data = objectArray.join([separator = ','])
console.log(address_data)
}
});
}
address("1000 Greenhill Blvd NW, Fort Payne, 35967, AL, USA");
const data = 'Column 19\n1\t2\t3\n4\t5\t6';
require('fs').writeFileSync('./Alabama_Pre_Final.tsv', data);
// i++;
// X(i);
}
}
}
I've looked at your answer above I think it should be easy enough to modify so that it works as you expect, I've done this below. The other functions should be left unchanged. So the function X processes each row then returns a record variable which we append to the records array. After processing is complete we write the records array to the csv file.
async function loadData(filePath) {
if (fs.existsSync(filePath)) {
var tsvData = fs.readFileSync(filePath, 'utf-8');
var rowCount = 0;
var scenarios = [];
parse_tsv(tsvData, (row) => {
rowCount++;
if (rowCount > 1) {
scenarios.push(row);
}
});
return scenarios;
} else {
console.log("loadData: Returning empty..")
return [];
}
}
// Process a row of TSV data
function X(row) {
return new Promise((resolve, reject) => {
if (row && row[7]) {
console.log(row[7]);
request({
url: 'https://us-extract.api.smartystreets.com/?auth-id=e62698e8-c3fc-b929-0f5b-d3b54d0bcd0c&auth-token=cibfMexBdl3HrmwbWY6p',
method: 'POST',
headers: { 'content-type': 'application/json' },
body: row[7],
},
(error, response, body) => {
if (!error && response.statusCode == 200) {
var res = JSON.parse(body);
let objectArray = [];
if (res.addresses[0].verified) {
objectArray.push(res.addresses[0].api_output[0].delivery_line_1, res.addresses[0].api_output[0].components.city_name,
res.addresses[0].api_output[0].components.zipcode, res.addresses[0].api_output[0].components.state_abbreviation)
}
var address_data = objectArray.join([separator = ','])
resolve({ name: address_data.replace(/['"]+/g, '') });
} else if (error) {
reject(error);
} else {
reject( { statusCode: response.statusCode });
}
});
}
});
}
async function processData() {
let MAX_RECORDS = 5; // Change as appropriate
var data = await loadData('./Alabama_Pre_Final.tsv');
if (data.length > 0) {
unProcessedItems = [];
let records = [];
for(let row of data) {
// Process a row of data.
let record = await X(row);
records.push(record);
if (records.length === MAX_RECORDS) break;
}
console.log(records);
csvWriter.writeRecords(records)
.then(() => console.log('The CSV file was written successfully'));
} else {
console.log("No Data");
}
}
processData();
const fs = require('fs');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
var rp = require('request-promise');
var dataToWrite;
var http = require("http");
var request = require('request');
function loadData(filePath) {
if (fs.existsSync(filePath)) {
var tsvData = fs.readFileSync(filePath, 'utf-8');
var rowCount = 0;
var scenarios = [];
parse_tsv(tsvData, (row) => {
rowCount++;
if (rowCount > 1) {
scenarios.push(row);
}
});
return scenarios;
} else {
return [];
}
}
function parse_tsv(s, f) {
var ix_end = 0;
for (var ix = 0; ix < s.length; ix = ix_end + 1) {
ix_end = s.indexOf('\n', ix);
if (ix_end == -1) {
ix_end = s.length;
}
//var row = s.substring(ix, ix_end - 1).split('\t');
var row = s.substring(ix, ix_end).split('\t');
f(row);
}
}
var unProcessedItems = [];
var data = loadData('./Alabama_Pre_Final.tsv');
var records = [];
async function X(i) {
if (data[i] && data[i][7]) {
console.log(data[i][7]);
var options = {
method: 'POST',
url: 'https://us-extract.api.smartystreets.com/?auth-id=c64de073-9531-9444-35e6-7204d9d62c36&auth-token=e5FxYc1niUD7Cp0peixd',
headers: {
'content-type': 'application/json'
},
body: data[i][7],
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(function (parsedBody) {
// POST succeeded...
var res = parsedBody;
let objectArray = [];
if (res.addresses.length) {
if (res.addresses[0].verified) {
objectArray.push(res.addresses[0].api_output[0].delivery_line_1, res.addresses[0].api_output[0].components.city_name,
res.addresses[0].api_output[0].components.zipcode, res.addresses[0].api_output[0].components.state_abbreviation)
}
var address_data = objectArray.join([separator = ','])
console.log(address_data)
// records.push({ name: address_data.replace(/['"]+/g, '') });
const ADDRESS_COLUMN_INDEX = 7;
for(let row of address_data) {
row[ADDRESS_COLUMN_INDEX] = await X(row[ADDRESS_COLUMN_INDEX]);
}
records.push(address_data.replace(/['"]+/g, ''));
let output = records.map(row => row.join("\t")).join("\n");
i++;
if (i <= 7) {
X(i);
}
else {
fs.writeFileSync('out.tsv', output);
console.log('The TSV file was written successfully');
// return callback(records);
}
}
});
}
// console.log(records);
}
if (data.length > 0) {
unProcessedItems = [];
X(0);
} else {
console.log("No Data");
}
I've updated this answer based on your last revisions, I hope this helps you:
function loadData(filePath) {
if (fs.existsSync(filePath)) {
var tsvData = fs.readFileSync(filePath, 'utf-8');
var rowCount = 0;
var scenarios = [];
parse_tsv(tsvData, (row) => {
rowCount++;
if (rowCount > 1) {
scenarios.push(row);
}
});
return scenarios;
} else {
return [];
}
}
function parse_tsv(s, f) {
var ix_end = 0;
for (var ix = 0; ix < s.length; ix = ix_end + 1) {
ix_end = s.indexOf('\n', ix);
if (ix_end == -1) {
ix_end = s.length;
}
var row = s.substring(ix, ix_end).split('\t');
f(row);
}
}
var unProcessedItems = [];
var data = loadData('./Alabama_Pre_Final.tsv');
var records = [];
async function X(i) {
if (data[i] && data[i][7]) {
console.log(data[i][7]);
var options = {
method: 'POST',
url: 'https://us-extract.api.smartystreets.com/?auth-id=c64de073-9531-9444-35e6-7204d9d62c36&auth-token=e5FxYc1niUD7Cp0peixd',
headers: {
'content-type': 'application/json'
},
body: data[i][7],
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(async function (parsedBody) {
// POST succeeded...
var res = parsedBody;
let objectArray = [];
if (res.addresses.length) {
if (res.addresses[0].verified) {
objectArray.push(res.addresses[0].api_output[0].delivery_line_1, res.addresses[0].api_output[0].components.city_name,
res.addresses[0].api_output[0].components.zipcode, res.addresses[0].api_output[0].components.state_abbreviation)
}
var address_data = objectArray.join([separator = ','])
console.log("rp.then -> address_data:",address_data);
data[i][7] = address_data.replace(/['"]+/g, '');
records.push(data[i].join("\t"));
i++;
if (i <= 7) {
console.log("Looking up address #" + i);
X(i);
} else {
const output = records.join("\n");
// Remove the _test when you are happy with the result.
fs.writeFileSync('./Alabama_Pre_Final_test.tsv', output);
console.log('The TSV file was written successfully');
}
}
});
}
}
if (data.length > 0) {
unProcessedItems = [];
X(0);
} else {
console.log("No Data");
}
Node.js database result return late inside the function
const db = req.app.db;
function getFeaturebyID(featureids) {
db.planFeatures.findOne({"_id": featureids }).then(features => {
return features.planFeaturesTitle;
});
}
const planLists ={};
db.planManagement.find({}).toArray((err, planList) => {
// res.end(JSON.stringify(planList));
featurearray = [];
var j =1;
planList.forEach(function(row) {
planLists._id = row._id;
features = row.planFeatures.split(',');
for (let i = 0; i < features.length; i++) {
featurearray[i] = getFeaturebyID(features[i]);
// console.log(getFeaturebyID(features[i]));
}
//row.planFeaturesName[j] = featurearray;
console.log(featurearray);
j++;
});
//console.log(planList);
// res.end(JSON.stringify(req.session));
res.render('stylist/plan_selection', {
top_results: planList,
title: 'Schedule',
config: req.app.config,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
showFooter: 'showFooter'
});
});
});
return features.planFeaturesTitle; return a value late while calling the function. I try callback but not works
This is due to asynchronous nature of node.js,
First declare your function async like this,
const getFeaturebyID = async (featureids) => {
const features = await db.planFeatures.findOne({"_id": featureids });
return features.planFeaturesTitle;
}
Then use it like this,
planList.forEach(async (row) => {
// your code here
for (let i = 0; i < features.length; i++) {
featurearray[i] = await getFeaturebyID(features[i]);
}
// your code here
});
I want to cache some data in node server:
rpc data provider like this:
var cnt = 0;
function rpcDataProvider(areaId) {
return Q.delay(100).then(() => {
cnt += 1
console.log("I am rpcDataProvider and I am not so fast. I am requested " + cnt + " times.");
const base = areaId * 10;
var arr = [];
for (var i = 0; i < 10; i ++) {
arr.push(base + i);
}
return arr;
})
}
http server
// cache data
var provinceList;
var cityList;
var countyList;
function getProvinceList() {
if (provinceList && provinceList.length > 0) return Q.resolve(provinceList);
return rpcDataProvider(1).then((rv) => {
provinceList = rv;
return rv;
});
}
function getCityList() {
if (cityList && cityList.length > 0) return Q.resolve(cityList);
return getProvinceList().then((provinceList) => {
return Q.all(provinceList.map((item) => rpcDataProvider(item))).then(rvs => {
cityList = rvs.reduce((prev, cur) => prev.concat(cur));
return cityList;
});
});
}
function getCountyList() {
if (countyList && countyList.length > 0) return Q.resolve(countyList);
return getCityList().then((cityList) => {
return Q.all(cityList.map((item) => rpcDataProvider(item))).then(rvs => {
countyList = rvs.reduce((prev, cur) => prev.concat(cur));
return countyList;
})
})
}
function api1() {
console.log("I am http api1");
return getProvinceList();
}
function api2() {
console.log("I am http api2");
return getCityList();
}
function api3() {
console.log("I am http api3");
return getCountyList();
}
function api4() {
console.log("I am http api4");
return getCountyList();
}
function api5() {
console.log("I am http api5");
return getCountyList();
}
client request:
function httpRequest() {
console.log("I am client.");
Q.all([api1(), api2(), api3(), api4(), api5()]);
}
httpRequest();
the problem is that parallel requests, the cache doest not work!
Don't cache the promise value. Cache the promise.
// cache data
var provinceList;
var cityList;
var countyList;
function rpcReduceAndConcat(list) {
return Q.all(list.map(rpcDataProvider)).then(rvs => {
return rvs.reduce((prev, cur) => prev.concat(cur));
});
}
function getProvinceList() {
if (!provinceList) provinceList = rpcDataProvider(1);
return provinceList;
}
function getCityList() {
if (!cityList) cityList = getProvinceList().then(rpcReduceAndConcat);
return cityList;
}
function getCountyList() {
if (!countyList) countyList = getCityList().then(rpcReduceAndConcat);
return countyList;
}