Skip to content

Commit f4a505c

Browse files
committed
support returning promise for async components (close vuejs#3527)
1 parent 982913f commit f4a505c

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

src/core/vdom/create-component.js

+28-22
Original file line numberDiff line numberDiff line change
@@ -189,30 +189,36 @@ function resolveAsyncComponent (
189189
factory.requested = true
190190
const cbs = factory.pendingCallbacks = [cb]
191191
let sync = true
192-
factory(
193-
// resolve
194-
(res: Object | Class<Component>) => {
195-
if (isObject(res)) {
196-
res = Vue.extend(res)
197-
}
198-
// cache resolved
199-
factory.resolved = res
200-
// invoke callbacks only if this is not a synchronous resolve
201-
// (async resolves are shimmed as synchronous during SSR)
202-
if (!sync) {
203-
for (let i = 0, l = cbs.length; i < l; i++) {
204-
cbs[i](res)
205-
}
192+
193+
const resolve = (res: Object | Class<Component>) => {
194+
if (isObject(res)) {
195+
res = Vue.extend(res)
196+
}
197+
// cache resolved
198+
factory.resolved = res
199+
// invoke callbacks only if this is not a synchronous resolve
200+
// (async resolves are shimmed as synchronous during SSR)
201+
if (!sync) {
202+
for (let i = 0, l = cbs.length; i < l; i++) {
203+
cbs[i](res)
206204
}
207-
},
208-
// reject
209-
reason => {
210-
process.env.NODE_ENV !== 'production' && warn(
211-
`Failed to resolve async component: ${String(factory)}` +
212-
(reason ? `\nReason: ${reason}` : '')
213-
)
214205
}
215-
)
206+
}
207+
208+
const reject = reason => {
209+
process.env.NODE_ENV !== 'production' && warn(
210+
`Failed to resolve async component: ${String(factory)}` +
211+
(reason ? `\nReason: ${reason}` : '')
212+
)
213+
}
214+
215+
const res = factory(resolve, reject)
216+
217+
// handle promise
218+
if (res && typeof res.then === 'function' && !factory.resolved) {
219+
res.then(resolve, reject)
220+
}
221+
216222
sync = false
217223
// return in case resolved synchronously
218224
return factory.resolved

test/unit/features/component/component-async.spec.js

+29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Vue from 'vue'
2+
import { Promise } from 'es6-promise'
23

34
describe('Component async', () => {
45
it('normal', done => {
@@ -130,4 +131,32 @@ describe('Component async', () => {
130131
done()
131132
}
132133
})
134+
135+
it('returning Promise', done => {
136+
const vm = new Vue({
137+
template: '<div><test></test></div>',
138+
components: {
139+
test: () => {
140+
return new Promise(resolve => {
141+
setTimeout(() => {
142+
resolve({
143+
template: '<div>hi</div>'
144+
})
145+
// wait for promise resolve and then parent update
146+
Promise.resolve().then(() => {
147+
Vue.nextTick(next)
148+
})
149+
}, 0)
150+
})
151+
}
152+
}
153+
}).$mount()
154+
expect(vm.$el.innerHTML).toBe('')
155+
expect(vm.$children.length).toBe(0)
156+
function next () {
157+
expect(vm.$el.innerHTML).toBe('<div>hi</div>')
158+
expect(vm.$children.length).toBe(1)
159+
done()
160+
}
161+
})
133162
})

0 commit comments

Comments
 (0)