Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returnable async promises #3527

Closed
smithb1994 opened this issue Aug 25, 2016 · 12 comments
Closed

Returnable async promises #3527

smithb1994 opened this issue Aug 25, 2016 · 12 comments

Comments

@smithb1994
Copy link

Vue.components allow promise (resolve, reject), but they don't allow returnable promises. I want to be able to return a promise for async components.
I want to do this:

Vue.component('async-component', function () {
  return new Promise(function (resolve, reject) {
    //step 1
  }).then(function () {
    //step 2
  }).then(function () {
    return { 
      template: '<p>hi</p>' 
    }
  })

})

new Vue({ 
    el: '#demo' 
})

rather than this:

Vue.component('async-component', function (resolve, reject) {
  new Promise(function (resolve, reject) {
    //step 1
  }).then(function () {
    //step 2
  }).then(function () {
    resolve({ 
      template: '<p>hi</p>' 
    })
  }).catch(function (error) {
    reject(error)
  })

})

new Vue({ 
    el: '#demo' 
})
@LinusBorg
Copy link
Member

What would be the advantage of this?

@smithb1994
Copy link
Author

It's just basic functionality that most async promise related things have.

@t2t2
Copy link

t2t2 commented Aug 28, 2016

Also helpful for webpack2 where code splitting is done with System.import which returns a promise (though might need an extra .default check?)

@JounQin
Copy link
Contributor

JounQin commented Aug 28, 2016

When we are using async components with .vue and webpack by component: resolve => require(['component'], resolve) in vue-router, but sometimes we still need async data in the .vue file, it can't resolve it very well right now.

I'm trying to use component: resolve => require(['component'], promise => promise.then(resolve)) and return a promise in the .vue file which returns a Vue component Object (componentObj) in the then callback, it works well but there's still a problem: it can't read the part of template in the .vue file, so I must apply the template string to the componentObj what makes the .vue file a little ugly.

So, my question is that is there any solution to resolve it or how about to support async promises in .vue file or how to get the part of template in the part of script😄.

@LinusBorg @yyx990803

A simple .vue:

<script>
  export default require('vue').http.get('/get-website-edit')
    .then(resp => {
      let wrapperTemplate = '';
      const components = {};

      resp.json().forEach(({data, template}, index) => {
        let component = `Component${index}`;
        wrapperTemplate += `<${component}/>`;
        components[component] = {
          data: () => data,
          template
        };
      });

      return {
        name: 'website-edit',
        template: '<ComponentsWrapper/>',
        components: {
          ComponentsWrapper: {
            template: `<div>${wrapperTemplate}</div>`,
            components
          }
        }
      };
    });
</script>

@yyx990803
Copy link
Member

@JounQin you should not attempt to export an async component in a *.vue file. Async components are always declared where they are used instead of defined.

@JounQin
Copy link
Contributor

JounQin commented Aug 28, 2016

@yyx990803 So how to resolve async data before create a Vue instance?

And it works well with resolve => require(['component'], promise => promise.then(resolve)).

Also, I'm trying to resolve async promise on the beforeEach function in the vue-router with vuex but it means I must to save all the data in the store so that I can read the initialized data with mapGetters.

simple code:

const init = meta.init;

// 需要预先拉取数据
  Vue.http[init.type || 'get'](init.url, {
    body: {
      ...route.params,
      ...route.query
    },
    ...init.options
  }).then(res => {
    const data = res.json();
    const actions = init.actions;
    // 完成后如果是字符串表示直接将所有数据导入 action
    if (typeof actions === 'string') {
      store.dispatch(actions, data);
    } else {
      // 否则应该是对象类型, 遍历将对应数据导入对应 action
      for (const [key, value] of Object.entries(actions)) {
        store.dispatch(key, data[value]);
      }
    }
    meta.fetched = true;
    // 数据导入 store 成功后进入组件
    next();
  });

But I also think it's very bad……

@yyx990803
Copy link
Member

@JounQin that's not the problem async components are trying to solve. Async components are designed for code splitting, not resolving data. To deal with async data, you create the instance first with a loading state, then fetch the data.

P.S. please don't hijack the issue for irrelevant questions.

@JounQin
Copy link
Contributor

JounQin commented Aug 28, 2016

I'm sorry but as I see, I and @smithb1994 are both trying finding a way to reolve async promise function before create a Vue instance so I commit the problems of myself here.

A final word: I used to create the instance first with a loading state but someone (our product designer for example) didn't like that 😅.

@posva
Copy link
Member

posva commented Aug 28, 2016

@JounQin if you need to fetch some data before displaying some components, it may be the time to use vue-router 😄

@JounQin
Copy link
Contributor

JounQin commented Aug 28, 2016

@posva Oh, of course I'm using it and I've tried to resolve the async promise on the beforeEach hook, but how to pass the resolved data to the initializing Vue instance on the beforeCreate hook? Then I use vuex to resolve it but I think it maybe a little high coupling and not all the data needs to save into store.

@posva
Copy link
Member

posva commented Aug 28, 2016

@JounQin Well that's another subject I'm sure you'll find information by searching on Google or the forums

@JounQin
Copy link
Contributor

JounQin commented Aug 28, 2016

Ok, thx and sorry again for bothering. @posva

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants