构建promise对象的有效方法

时间:2017-11-15 13:51:44

标签: javascript ecmascript-6 promise

目前我所拥有的是:

    getData(user) {
     return this.$q.all({
        userInfo: this.$http.get(this.buildUrl('user.getinfo', user)),
        userTopArtists: this.$http.get(this.buildUrl('user.gettopartists', user)),
        userChart: this.$http.get(this.buildUrl('user.getWeeklyChartList', user))
            .then(resp => {
                let promises = [];
                let data = resp.data.weeklychartlist.chart;
                for (let i = data.length - 4; i < data.length; i++) {
                    promises.push(
                        this.$http.get(this.buildUrl('user.getWeeklyTrackChart', user) + `&from=${data[i].from}&to=${data[i].to}`)
                        .then(resp => {
                            return resp.data.weeklytrackchart.track.length;
                        })
                    );
                }

                return this.$q.all(promises);
            })
    }).then(resp => {
        return resp;
    }).catch(err => {
        this.$q.reject('Error' + err.status);
    })
}

但我认为可能有一种更实用的方法来构建这个promise对象,因为很多代码都在重复。所以我试着想出一个更好的解决方案:

    buildPromiseObj(target) {
     const methods = ['getinfo', 'gettopartists', 'getweeklychartlist'];
     let obj = {};
     for ( let method in methods ) {
        obj[`${methods[method]}`] = this.$http.get(this.buildUrl(`${target}.${methods[method]}`, target))
    }
}
  1. 这种方法是否有意义,我应该使用吗?
  2. 您可以看到我在第一个函数中发出的第三个请求有其他嵌套请求。我有什么方法可以将其整合到我上面写的方法中?

2 个答案:

答案 0 :(得分:3)

是的,像这样概括总是一个好主意。但是:

关于图表列表,您可以在致电then之前向承诺附加另一个all。此外,您可以通过使用更具功能性的方法来大大简化回调:

getData(user) {
    const methods = ['Info', 'TopArtists', 'WeeklyChartList'];
    let promises = {};
    for (let method of methods) {
        obj['user' + method] = this.$http.get(this.buildUrl('user.get'+method.toLowerCase(), target));
    }
    promises.userWeeklyChartList = promises.userWeeklyChartList.then(resp =>
         this.$q.all(resp.data.weeklychartlist.chart.slice(-4).map(val =>
             this.$http.get(this.buildUrl('user.getWeeklyTrackChart', user) + `&from=${val.from}&to=${val.to}`)
         ).then(resp =>
             resp.data.weeklytrackchart.track.length
         ))
    );
    return this.$q.all(promises).catch(err => {
        throw new Error(err.status);
    });
}

答案 1 :(得分:1)

作为第一关,这就是我要做的事情。

&#13;
&#13;
        
const { $http: { get }, $q: { all } } = this,
      // convert { x: 'a', y: 'b' } to '&x=a&y=b'
      paramStr = obj => Object.entries(obj).map(([k,v]) => `&${k}=${v}`).join(), // You might not have Object#entries; it's new
      
      getUrl = (target, method, params={}) => this.buildUrl(`user.get${method}`, target) + paramStr(params),

      getData = user => all(Object.assign({},
        ...['info', 'topartists', 'WeeklyChartList'].map(m => get(getUrl(user, m)))
      ))
        .then(([ userInfo, userTopArtists, { data: { weeklychartlist: { chart } } } ]) => 
          all({
            userInfo, 
            userTopArtists,
            userChart: all([
                ...chart.slice(-4)
                  .map(({ from, to }) => 
                    get(getUrl(target, 'WeeklyTrackChart', { from, to }))
                      .then(({ data: { weeklytrackchart: { track: { length } } } }) => length)
                  )
              ])
          })
        )
        .catch(({ status }) => this.$q.reject(`Error${status}`));
&#13;
&#13;
&#13;

尽管Bergi的建议很好,但我保持你的代码在功能上是一样的。