如何在不创建闭包的情况下继承promise链中的数据?

时间:2015-09-25 19:16:15

标签: javascript promise bluebird

以下是工作代码的示例:

request('http://foo.com/')
    // Collect list of locations.
    .then(function (response) {
        let $ = response.data,
            locations = [];

        $('a[href^="/venues/"]').each(function () {
            locations.push({
                name: $(this).text(),
                url: 'http://foo.com/' + $(this).attr('href')
            });
        });

        return locations;
    })
    // Retrieve additional information about locations.
    .map((location) => {
        return request(location.url)
            .then((response) => {
                // Combine location specific information with the initial location information.
                response;
                location;
            });
    }, {
        concurrency: 5
    });

在上面的示例中,我向" foo.com"发出请求,获取位置列表,然后使用位置数据查询" foo.com"有关位置的其他信息。最后,我将位置特定信息与初始位置信息结合起来。

我不喜欢上面的代码,它是不平坦的。如果特定于位置的查询需要额外的异步信息,并且子级需要更多额外的异步信息,则代码将变成回调地狱。

我想将代码转换为扁平结构,例如(伪代码)

request('http://foo.com/')
    // Collect list of locations.
    .then(function (response) {
        let $ = response.data,
            locations = [];

        $('a[href^="/venues/"]').each(function () {
            locations.push({
                name: $(this).text(),
                url: 'http://foo.com/' + $(this).attr('href')
            });
        });

        return locations;
    })
    // Retrieve additional information about locations.
    .map((location) => {
        return request(location.url);
    }, {
        concurrency: 5
    })
    // Filter list of responses.
    .filter((response) => {
        return response.incomingMessage.statusCode === 200;
    })
    // Combine location specific information with the initial location information.
    .map((response) => {
        // How to access "location" and "response"?
    });

实现它的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

我能想到的唯一方法是通过增加请求的响应来获取有关某个位置的其他数据,例如

.map((location) => {
    return request('http://foo.com/' + location.nid)
        .then((response) => {
            return {
                location: location,
                response: response
            };
        });
}, {
    concurrency: 5
})

这样整个Promise链或多或少都会持平。

request('http://foo.com/')
    // Collect list of locations.
    .then(function (response) {
        let $ = response.data,
            locations = [];

        $('a[href^="/venues/"]').each(function () {
            locations.push({
                nid: $(this).attr('href'),
                name: $(this).text(),
                url: 'http://foo.com/' + $(this).attr('href')
            });
        });

        return locations;
    })
    // Retrieve additional information about locations.
    .map((location) => {
        return request('http://foo.com/' + location.nid)
            .then((response) => {
                return {
                    location: location,
                    response: response
                };
            });
    }, {
        concurrency: 5
    })
    // Filter list of responses.
    .filter((response) => {
        return response.response.incomingMessage.statusCode === 200;
    })
    .map((response) => {
        // Combine location specific information with the initial location information.
        response.response;
        response.location;
    });

答案 1 :(得分:0)

如果在request()之后执行bind({}),则链中的函数将具有可用于存储内容的this对象。

示例:

Promise.resolve('A').bind({}).then(function(value){
    this.value = value;
    return 5;
}).then(function(number) {
    this.number = number;
}).then(function() {
    console.log(this);
})

输出:

{ value: 'A', number: 5 }