Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions lib/db.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,51 @@
const Tapable = require('tapable')
const {
SyncWaterfallHook,
AsyncSeriesWaterfallHook
} = require('tapable')

class DB extends Tapable {
constructor() {
class DB {
constructor(options) {
// TODO
this.options = options ? options : {}

this.hooks = {
endpoint: new AsyncSeriesWaterfallHook(['options']),
options: new SyncWaterfallHook(['options']),
judge: new SyncWaterfallHook(['res']) // 使用SyncWaterfallHook才会有返回值
}
}

modifyOptions(options) {
this.hooks.options.call(options)

Object.keys(options).forEach(key => {
if (options.hasOwnProperty(key)) {
this.options[key] = options[key]
}
})
}

request() {
request(options) {
if (options) {
this.modifyOptions(options)
}

// TODO
return this.hooks.endpoint
.promise(this.options)
.then(res => {
const judge = this.hooks.judge.call(res)

if (!judge) {
throw res
}

return res
})
.catch(err => {
return Promise.reject(err)
})
}
}

module.exports = DB
module.exports = DB
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"webpack": "^3.5.3"
},
"dependencies": {
"tapable": "^2.2.1",
"puppeteer": "^16.2.0"
}
}
146 changes: 96 additions & 50 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ describe('DB', function () {
constructor(options) {
super(options)

this.plugin('endpoint', function () {
return new Promise((resolve) => {
this.hooks.endpoint.tapPromise('endpoint', function () {
return new Promise(resolve => {
setTimeout(() => {
resolve({ retcode: 0, res: { msg: 'hello world' } })
}, 0)
Expand All @@ -27,47 +27,70 @@ describe('DB', function () {
}
}

const xx = new XX()
xx.request()
.then((res) => {
assert.equal(res.res.msg, 'hello world')
done()
})
const xx = new XX({})
xx.request().then(res => {
assert.equal(res.res.msg, 'hello world')
done()
})
})

it('可以根据不同的options,使用不同的endpoint', function (done) {
class AA extends DB {
constructor(options) {
super(options)
this.plugin('endpoint', function (options) {

/*
梳理一下流程:
1. 第一次请求时,type为1,会先执行endpoint1,将{ retcode: 1, msg: 'logout' }传递给endpoint2
2. endpoint2接收到{ retcode: 1, msg: 'logout' }后,走else逻辑,将其传递给第一次请求的then回调
3. 发出第二次请求,type为0,先执行endpoint1,走else逻辑,将{ type: 0 }传递给endpoint2
4. endpoint2接收到{ type: 0 },会将{ retcode: 0, res: { msg: 'hello world' } }传递给第二个then回调
*/

this.hooks.endpoint.tapPromise('endpoint1', function (options) {
if (options.type === 1) {
return new Promise((resolve) => {
return new Promise(resolve => {
setTimeout(() => {
resolve({ retcode: 1, msg: 'logout' })
}, 0)
})
} else {
// AsyncSeriesWaterfallHook需要将返回值传递给下一个函数
return new Promise(resolve => {
setTimeout(() => {
resolve(options)
}, 0)
})
}
})
this.plugin('endpoint', function (options) {

this.hooks.endpoint.tapPromise('endpoint2', function (options) {
if (options.type === 0) {
return new Promise((resolve) => {
return new Promise(resolve => {
setTimeout(() => {
resolve({ retcode: 0, res: { msg: 'hello world' } })
}, 0)
})
} else {
return new Promise(resolve => {
setTimeout(() => {
resolve(options)
}, 0)
})
}
})
}
}

const aa = new AA
const aa = new AA()
// 如果 options.type === 1,则返回第一个答案
aa.request({ type: 1 })
.then(res => {
assert.equal(res.retcode, 1)
// 如果 options.type === 0,则返回第二个答案
return aa.request({ type: 0 })
}).then(res => {
})
.then(res => {
assert.equal(res.retcode, 0)
done()
})
Expand All @@ -77,12 +100,12 @@ describe('DB', function () {
class YY extends DB {
constructor(options) {
super(options)
this.plugin('options', (options) => {
this.hooks.options.tap('options', options => {
// modify options
options.flag = true
return options
})
this.plugin('endpoint', (options) => {
this.hooks.endpoint.tapPromise('endpoint', options => {
// init
assert.equal(options.init, true)
// merge
Expand All @@ -100,31 +123,30 @@ describe('DB', function () {
}

const yy = new YY({ init: true })
yy.request({ url: 'my://hello' })
.then((res) => {
done()
})
yy.request({ url: 'my://hello' }).then(res => {
done()
})
})

it('可以设置多个options插件', function (done) {
class BB extends DB {
constructor(options) {
super(options)
this.plugin('options', (options) => {
this.hooks.options.tap('options', options => {
// modify options
options.flag = true
return options
})
this.plugin('options', (options) => {
this.hooks.options.tap('options', options => {
// modify options,后面的覆盖前面的
options.flag = false
return options
return options
})
this.plugin('options', (options) => {
this.hooks.options.tap('options', options => {
options.url = 'you://hello'
return options
})
this.plugin('endpoint', (options) => {
this.hooks.endpoint.tapPromise('endpoint', options => {
// init
assert.equal(options.init, true)
// merge
Expand All @@ -142,74 +164,98 @@ describe('DB', function () {
}

const bb = new BB({ init: true })
bb.request({ url: 'my://hello' })
.then((res) => {
done()
})
bb.request({ url: 'my://hello' }).then(res => {
done()
})
})

it('可以通过judge插件判断返回是否正确', function (done) {
class CC extends DB {
constructor(options) {
super(options)
this.plugin('endpoint', function (options) {

this.hooks.endpoint.tapPromise('endpoint', function (options) {
if (options.type === 1) {
return new Promise((resolve) => {
return new Promise(resolve => {
setTimeout(() => {
resolve({ retcode: 1, msg: 'logout' })
}, 0)
})
} else {
return new Promise(resolve => {
setTimeout(() => {
resolve(options)
}, 0)
})
}
})
this.plugin('endpoint', function (options) {

this.hooks.endpoint.tapPromise('endpoint', function (options) {
if (options.type === 0) {
return new Promise((resolve) => {
return new Promise(resolve => {
setTimeout(() => {
resolve({ retcode: 0, res: { msg: 'hello world' } })
}, 0)
})
} else {
return new Promise(resolve => {
setTimeout(() => {
resolve(options)
}, 0)
})
}
})

this.plugin('judge', function (res) {
if (res.retcode !== 0) return true
this.hooks.judge.tap('judge', function (res) {
// retcode为0表示请求成功
// 如果没有注册judge hook,会将res直接返回
return res.retcode === 0
})
}
}

const cc = new CC
const cc = new CC()
cc.request({ type: 0 })
.then((res) => {
.then(res => {
assert.equal(res.res.msg, 'hello world')
return cc.request({ type: 1 })
}).then((res) => {
done(new Error('不应该进入正确回调,应当进入失败回调,因为retcode为1'))
}, (res) => {
assert.equal(res.retcode, 1)
assert.equal(res.msg, 'logout')
done()
})
.then(
res => {
done(
new Error('不应该进入正确回调,应当进入失败回调,因为retcode为1')
)
},
res => {
assert.equal(res.retcode, 1)
assert.equal(res.msg, 'logout')
done()
}
)
})

it('可以reject数据', function (done) {
class ZZ extends DB {
constructor(options) {
super(options)
this.plugin('endpoint', function () {

this.hooks.endpoint.tapPromise('endpoint', function () {
return new Promise((resolve, reject) => {
reject()
})
})
}
}

const zz = new ZZ
const zz = new ZZ()

zz.request()
.then(() => {
zz.request().then(
() => {
done(new Error('should not trigger resolve callback'))
}, () => {
},
() => {
done()
})
}
)
})
})
})