注文データクリーニング、データ容量10W +:最近需要を受けました。
ロジックを実装するために面倒で複雑です:
すべてのユーザーが招待ID番号を取得循環- >招待客のユーザートークンIDを取得するには- - >招待IDの招待サイクルの対応するID番号のすべてを取得する>ユーザーのすべてのトークンFOUND受注- >ループチェック(返金するかどうかを決定する)すべての注文の状況- >あなたは赤い封筒人々のインセンティブを招待し、対応する還付取り消した場合-赤いはしごを生成するために招待した人の数を再計算するために、現金報酬普通の封筒を控除した後に>。
ビジネスコードは確かに非常に非常に複雑な複雑で、最も重要なことは、招待者に人を招待することで、多くの関係している、人々は、注文の詳細を取るために招待され、サイクルのために、多くの関係で様々なドーピング判断とトリプルですしたい場合がありますその上で稼働しているサーバー上のデータクリーニングインターフェイスに関する知識と、影響が重大です。
したがって、私は、インターフェイスの緩和の生産圧力インタフェースラインに分け、ここでオンライン呼び出します。次のように具体的な手順は次のとおりです。
1:ローカル各道に沿って、各洗浄プロセスのみ1人の被招待者のための生産環境で生産・インタフェース・招待者ID、渡された取得します。
2:原因は、異なる開発環境と本番環境のデータベースなので、本番環境へのJSONファイルをエクスポートするすべての人々を招待します。
3:JSONファイルの行を読むためのローカルの開発環境は、それぞれの人のIDは、きれいなインターフェースの生産への招待状を渡します。
4:非常に長いロジックため、4秒の送信遅延間隔を使用しています。(3〜5秒のインタフェース試験)
まあ、今のコードでは、ビジネスコードを無視して、ここではそれを自分自身を学習の記録は次のとおりです。
ライブラリは、実際の本番環境ID輸出JSONの生産を開始するために人々を招待します。
カジュアルな場所に、そのノードは、JSONファイルを読み込みます。
ピット:
(1)は、絶対パスを記述する必要がありますファイルを読み取るために、ファイルへの相対パスが見つかりません!
(2)FSはString型で読み出して、自分自身の言葉を加えたデータの種類を見て信じていません。JSONは、JSONのタイプのように見えるわけではないということです。
同期に押し込まない限り、コールバック関数値に装着されている(3)は、役に立ちません。あなたが見に()をCONSOLE.LOGさまざまな場所を所有することができると信じてはいけません。
// 先引入
const fs = require('fs');
fs.readFile(
// 注意这里一定要写绝对路径,相对路径无法识别。
'/Users/XXXX/Desktop/XXXXX_project/XXXXapi/app/controller/data.json',
'utf8',
async function(err, data) {
if (err) {
console.log(err);
}
// 一定要JSON转了才是JSON格式,不然读取都是String。
const dataList = JSON.parse(data);
},
);
睡眠への睡眠のJAVAノード()スレッドが存在しないため、そのプロセスは、自分の睡眠()を達成できるようにします。時間は秒数で渡されるその定義です。
function sleep(times) {
let now = new Date();
const exit = now.getTime() + times;
while (true) {
now = new Date();
if (now.getTime() > exit) {
return;
}
}
}
最後に、完全なコードを見て:
ピット:
ループ遅延タスクのために使用するのに適していない(1)のsetTimeoutは、私はサイケのsetTimeoutだっ開始、しかし慎重に考えて:
A:内側にsetTimeoutを、のために、その後第2の遅延Nを完了する瞬間があるという場合には以下のため、各データに到達数秒遅れて、その後、次のデータを獲得しました。
B:外のsetTimeoutに、それは(あなたが経験を所有することができ、説明するのは難しい)要素の集合として数回同じ出力を繰り返し続けるためならば
強制辞職自分の睡眠を達成()。
async test() {
fs.readFile(
'/Users/自己文件存放的位置/data.json',
'utf8',
async function(err, data) {
if (err) {
console.log(err);
}
const dataList = JSON.parse(data);
for (const item of dataList.record) {
sleep(4000); // 停滞四秒
const res = await axios.get(
`https://线上接口的域名+路径?invite_user_id=${item.invite_user_id}`,
);
console.log(item.invite_user_id);
console.log(res.data);
}
},
);
function sleep(times) {
let now = new Date();
const exit = now.getTime() + times;
while (true) {
now = new Date();
if (now.getTime() > exit) {
return;
}
}
}
this.ctx.success();
}
この部分は慎重に検討する必要はありません!!!オンライン面倒な清掃業務コードは、長い洗浄プロセスは読んでいません。ライン、これらのビジネスコードなし基準値のビジネスによります。それは、このデザインパターンをとる前に、長いですので、それはまたです。
/**
* 清洗退费用户接口
*/
async cleanRefundUser() {
// 首先根据邀请者ID拿到全部被邀请者ID,再用被邀请者ID,也就是newcomer ID去users表拿accesstoken,再用token去查用户订单。
const inviteUserId = this.ctx.query.invite_user_id;
let accessToken;
let noRefund = 0;
let refund = 0;
const userIdList = await this.inviteVacationClass.getAllUserIdByInviteUserId(
inviteUserId,
);
logger.info(LOG_CAT, {
msg: '清洗数据开始',
data: {
inviteUserIds: inviteUserId,
userIdLists: userIdList,
},
});
let ordersActivity;
for (const id of userIdList) {
// 拿被邀请者的token
const userAccessToken = await this.inviteVacationClass.getAccessTokenByUserId(
id.newcomer_id,
);
if (userAccessToken) {
accessToken = userAccessToken.access_token;
}
// 用token去查询订单,注意这里会返回多个订单!
const res = await axios.get(
`${this.app.config.get_teacher_info_api}/api/1/pay/get_order_list?access_token=${accessToken}`,
);
if (res && res.data.data.finish_sub_orders[0]) {
for (const item of res.data.data.finish_sub_orders) {
ordersActivity = item.activity;
// 判断是否老带新活动
if (
// 过滤掉不是老带新活动的订单
ordersActivity === '2019grow50yuanldx' ||
ordersActivity === '2019grow50yuanldx_bzr_xiaoxue' ||
ordersActivity === '2019grow50yuanldx_bzr_chuzhong' ||
ordersActivity === '2019grow50yuanldx_xiaodi' ||
ordersActivity === '2019grow50yuanldx_chuzhong' ||
ordersActivity === '2019grow50yuanhanjia_jiesuo_50'
) {
// 订单状态判断:1 已支付 2 退费 0 未付款 3 取消
let orderStatus;
orderStatus = item.status;
if (orderStatus === 1) {
noRefund = noRefund + 1;
} else if (orderStatus === 2) {
// 再根据newcommer id 和 invite user id拿到对应哪个红包。
const redPocket = await this.ctx.app.dao.inviteNewcomerV2.inviteRedpocket.getRedPocketById(
inviteUserId,
id.newcomer_id,
);
if (redPocket[0][0]) {
// 把该普通固定奖励红包设置为退费状态,不可领取
await this.ctx.app.dao.inviteNewcomerV2.inviteRedpocket.cancelRedPocketById(
redPocket[0][0].id,
new Date(),
);
}
logger.info(LOG_CAT, {
msg: '用户退费信息',
data: {
newcomer_id: id.newcomer_id,
inviteUserIds: inviteUserId,
redPocketId: redPocket[0][0].id,
redPockets: redPocket[0][0],
},
});
refund = refund + 1;
}
}
}
}
}
logger.info(LOG_CAT, {
msg: '清洗普通红包结束,开始统计剩余人数',
data: {
inviteUserIds: inviteUserId,
noRefunds: noRefund,
refunds: refund,
},
});
// 假如未退费好友小于10人,要扣除100元阶梯红包,其它实物奖励不用管。
if (noRefund < 10) {
const redpocketType = 25;
await this.ctx.app.dao.inviteNewcomerV2.inviteRedpocket.cancelExtraRedPocket(
inviteUserId,
new Date(),
redpocketType,
);
}
this.ctx.success('未退费人数:' + noRefund, '退费人数:' + refund);
}