Skip to content

Commit e7a066f

Browse files
committed
Merge branch 'async-improvements' into dev
2 parents 7d3c883 + ae07fed commit e7a066f

File tree

2 files changed

+67
-29
lines changed

2 files changed

+67
-29
lines changed

src/core/vdom/helpers/resolve-async-component.js

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,100 @@
11
/* @flow */
22

3-
// () => ({
4-
// component: import('./xxx.vue'),
5-
// delay: 200,
6-
// loading: LoadingComponent,
7-
// error: ErrorComponent
8-
// })
9-
103
import {
114
warn,
5+
once,
6+
isDef,
7+
isUndef,
8+
isTrue,
129
isObject
1310
} from 'core/util/index'
1411

12+
function ensureCtor (comp, base) {
13+
return isObject(comp)
14+
? base.extend(comp)
15+
: comp
16+
}
17+
1518
export function resolveAsyncComponent (
1619
factory: Function,
1720
baseCtor: Class<Component>,
1821
context: Component
1922
): Class<Component> | void {
20-
if (factory.resolved) {
23+
if (isTrue(factory.error) && isDef(factory.errorComp)) {
24+
return factory.errorComp
25+
}
26+
27+
if (isDef(factory.resolved)) {
2128
return factory.resolved
2229
}
2330

24-
const cb = () => context.$forceUpdate()
25-
if (factory.requested) {
26-
// pool callbacks
27-
factory.pendingCallbacks.push(cb)
31+
if (isTrue(factory.loading) && isDef(factory.loadingComp)) {
32+
return factory.loadingComp
33+
}
34+
35+
if (isDef(factory.contexts)) {
36+
// already pending
37+
factory.contexts.push(context)
2838
} else {
29-
factory.requested = true
30-
const cbs = factory.pendingCallbacks = [cb]
39+
const contexts = factory.contexts = [context]
3140
let sync = true
3241

33-
const resolve = (res: Object | Class<Component>) => {
34-
if (isObject(res)) {
35-
res = baseCtor.extend(res)
42+
const forceRender = () => {
43+
for (let i = 0, l = contexts.length; i < l; i++) {
44+
contexts[i].$forceUpdate()
3645
}
46+
}
47+
48+
const resolve = once((res: Object | Class<Component>) => {
3749
// cache resolved
38-
factory.resolved = res
50+
factory.resolved = ensureCtor(res, baseCtor)
3951
// invoke callbacks only if this is not a synchronous resolve
4052
// (async resolves are shimmed as synchronous during SSR)
4153
if (!sync) {
42-
for (let i = 0, l = cbs.length; i < l; i++) {
43-
cbs[i](res)
44-
}
54+
forceRender()
4555
}
46-
}
56+
})
4757

48-
const reject = reason => {
58+
const reject = once(reason => {
4959
process.env.NODE_ENV !== 'production' && warn(
5060
`Failed to resolve async component: ${String(factory)}` +
5161
(reason ? `\nReason: ${reason}` : '')
5262
)
53-
}
63+
if (isDef(factory.errorComp)) {
64+
factory.error = true
65+
forceRender()
66+
}
67+
})
5468

5569
const res = factory(resolve, reject)
5670

57-
// handle promise
58-
if (res && typeof res.then === 'function' && !factory.resolved) {
59-
res.then(resolve, reject)
71+
if (isObject(res)) {
72+
if (typeof res.then === 'function') {
73+
// () => Promise
74+
if (isUndef(factory.resolved)) {
75+
res.then(resolve, reject)
76+
}
77+
} else if (isDef(res.component) && typeof res.component.then === 'function') {
78+
if (isDef(res.error)) {
79+
factory.errorComp = ensureCtor(res.error, baseCtor)
80+
}
81+
82+
if (isDef(res.loading)) {
83+
factory.loadingComp = ensureCtor(res.loading, baseCtor)
84+
setTimeout(() => {
85+
if (isUndef(factory.resolved) && isUndef(factory.error)) {
86+
factory.loading = true
87+
forceRender()
88+
}
89+
}, res.delay || 200)
90+
}
91+
92+
if (isDef(res.timeout)) {
93+
setTimeout(reject, res.timeout)
94+
}
95+
96+
res.component.then(resolve, reject)
97+
}
6098
}
6199

62100
sync = false

src/shared/util.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,10 +250,10 @@ export function looseIndexOf (arr: Array<mixed>, val: mixed): number {
250250
*/
251251
export function once (fn: Function): Function {
252252
let called = false
253-
return () => {
253+
return function () {
254254
if (!called) {
255255
called = true
256-
fn()
256+
fn.apply(this, arguments)
257257
}
258258
}
259259
}

0 commit comments

Comments
 (0)