返回下一个函数来调用javascript

时间:2017-09-07 16:24:51

标签: javascript ecmascript-6 es6-promise

试图解释我正试图解决的问题的解决方案。使用vue.js或实际上并不重要哪个框架,它更像是一个javascript问题。我写了一个集成了soundcloud api的模块。 trackBySearchTerm函数发出http请求以搜索具有给定术语但每页指定5个结果的歌曲。现在要获取下一页,api返回的响应包含属性next_href。 next_href是用于进行下一次api调用的url。所以我发现我的实现真的很糟糕。这是我写的模块:

import http from 'axios'

const clientId = '1234'
const scApiBaseUrl = 'https://api.soundcloud.com/'
const scBaseUrl = 'http://soundcloud.com/'
const pageSize = 6

export default { 
    tracksBySearchTerm (p, cb) {
        let initialUrl = scApiBaseUrl + 'tracks/' + '?client_id=' + clientId + '&limit=' + pageSize + 
        '&linked_partitioning=1'

        if (p.searchTerm) {
            initialUrl += '&q=' + encodeURIComponent(p.searchTerm)
        }

        let url = p.nextHref || initialUrl

        http.get(url, { withCredentials: false })
            .then((result) => { cb( result.data )  } ) 
    }
}

所以现在,promise的后续部分使用soundclouds api的响应调用回调。真正糟糕的部分是next_href在响应中,但是被提供给回调函数。 tracksBySearchTerm p参数可以包含nextHref属性,如果存在,则使用该URL作为http请求。我真的不喜欢这个,因为这意味着任何使用此模块的人都可以传递任何随机网址。

所以我想我正在寻找的解决方案是我如何让trackBySearchTerm将getNextResults函数作为参数传递给回调函数(显然是带有分页搜索结果),调用后将使用来自的next_href先前发出api请求的请求,也适用于下一组页面。这意味着可能有10页的结果。我也试图避免全局的next_href变量,因为模块应该只返回下一组结果。

1 个答案:

答案 0 :(得分:0)

首先:不要使用静态方法默认导出对象,也不要使用回调但返回promises。

是的,您可以轻松构造一个新对象以返回到具有获取下一个结果的方法的调用者。你只需使用一个基本的闭包:

import http from 'axios'

const clientId = '1234'
const scApiBaseUrl = 'https://api.soundcloud.com/'
const scBaseUrl = 'http://soundcloud.com/'
const pageSize = 6

function tracksByUrl(url) {
    return http.get(url, { withCredentials: false }).then(response => {
        return {
            result: response.data,
            next() {
                return tracksByUrl(response.nextHref);
            }
        };
    });
}

export function tracksBySearchTerm (searchTerm) {
    let initialUrl = `${scApiBaseUrl}tracks/?client_id=${clientId}&limit=${pageSize}&linked_partitioning=1`;
    if (searchTerm) {
        initialUrl += '&q=' + encodeURIComponent(searchTerm)
    }
    return tracksByUrl(initialUrl);
}