Appearance
plugin
javascript
class Store {
constructor (options = {}) {
this._actionSubscribers = []
this._subscribers = []
// 插件就是一个函数,构造器中会遍历配置项中的 plugins 数组并将里面的每个函数执行的
// 同时传入 store,插件只会执行这一次,这一次执行会完成插件初始化和回调收集。
// store._subscribers 中保存着所有插件的回调,插件内部通过 store.subscribe
// 收集回调,接收 fn 和 options 两个参数,如果 store._subscribers.indexOf(fn)
// >= 0,那么根据 options.prepend 是否为真决定添加到回调数组的最前面还是最后面。
// 添加完后返回一个函数用于删除回调,这个函数调用时会获取该回调在数组中的位置,
// 并通过 splice 在数组 store._subscribers 删除该回调。
// 在 commit 方法中最后会将 store._subscribers 中的每个 fn 执行,因此插件的回调
// 只有在 mutation 执行完后才会执行,fn 执行时会传入 mutation 和 state。
// 当然回调也可以保存在 store._actionSubscribers 中,这里保存的每一项是对象
// 如果你传的是 fn,会包装成 { before: fn },意味着 fn 会在 在 action 执行前执行
// 你可以手动配置成 { after: fn } 或 { error: fn },意味着 fn 会在 action 执行
// 完后执行或出错时执行
// apply plugins
plugins.forEach(plugin => plugin(this))
}
commit (type, payload) {
const entry = this._mutations[type]
if (!entry) {
return
}
entry.forEach(function commitIterator (handler) {
handler(payload)
})
this._subscribers
.slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
.forEach(sub => sub(mutation, this.state))
}
dispatch (type, payload) {
const entry = this._actions[type]
if (!entry) {
return
}
this._actionSubscribers
.slice() // shallow copy to prevent iterator invalidation if subscriber synchronously calls unsubscribe
.filter(sub => sub.before)
.forEach(sub => sub.before(action, this.state))
const result = entry.length > 1
? Promise.all(entry.map(handler => handler(payload)))
: entry[0](payload)
return new Promise((resolve, reject) => {
result.then(res => {
this._actionSubscribers
.filter(sub => sub.after)
.forEach(sub => sub.after(action, this.state))
resolve(res)
}, error => {
this._actionSubscribers
.filter(sub => sub.error)
.forEach(sub => sub.error(action, this.state, error))
reject(error)
})
})
}
}