我如何组织承诺链并轻松对其进行检验?

时间:2019-05-15 12:19:54

标签: javascript promise

我如何组织承诺链并轻松对其进行检验?

我从发出三个http请求(API调用)的代码开始,如下所示

function A(group_list){
    var all_promises = [];
    for (let group_id of group_list) {

        var pr = fetch('/validate_group_id')
            .then(response => response.json())
            .then(json_data => {
                if (json_data.Error === null) {
                    ...
                    return B(group_id);
                }
            });
        all_promises.push(pr);
    }

    return Promise.all(all_promises);
}

function B(group_id) {
    return fetch('/process_group_id')
        .then(response => response.json())
        .then(json_data => {
            ...
            console.log(group_id);
        })
        .catch(error => {... /* log error */ })
}

function C(){
    var group_list = [...];

    A(group_list)
    .then(result => {
        fetch('/update_group_list')
        .then(response => response.json())
        .then(json_data => {
            ...
            console.log('group list updated ')

            // or create another promise
        })
    })
}

它紧密耦合且难以测试。我想重构它以便能够分别测试每个功能。我试图这样做,结果得到了这样的东西。

function A(data) {
    return fetch('/validate_group_id', {..., body: data})
        .then(response => response.json());
        .catch(error => {
            console.log(error);
        });
}

function B(value_from_handle_A_result, data) {
    // somehow I need to pass group_id and data here
    return fetch('/process_group_id', {..., body: data})
        .then(response => response.json())
        .then(json_data => {
            ...
            console.log(group_id);
        })
        .catch(error => {... /* log error */ });
}


function handle_A_result(result) {
    return Promise((resolve, reject) => {
        if (result === undefined) console.log('fetch general error');
        if (result.Error === null) { 
            console.log(`group ${group_id} is ok`);  // here I need access to group_id
            resolve('ok');
        } else {
            console.log(`group ${group_id} is not ok`);
            reject('cancelled');
        }
    }
}

function handle_B_result(...) {
    ...
}

function C(group_list) {
    var all_promises = [];
    for (let group_id of group_ids) {
        data = ...

        let p = this.A(data);
        // because handle_A_result need access to group_id I have to pass it from A() or use for handle_A_result.bind(...)
        // or wrap handle_A_result() here with other function
        p = p.then(handle_A_result);

        // in B I need to pass data
        data_for_B = ...
        p.then(B) 
        p.then(handle_B_result) // here again I need access to group_id
        p.catch(error => 'aborted') // catch "cancelled promises"
        ...

        all_promises.push(p);
    }
    return Promise.all(all_promises);
}

结果函数A(),B(),handle_A_result(),handle_B_result()可以分别测试,但C()变得复杂。我介绍了新的复杂性-在函数中传递参数。 我认为,存在其他方法可以很容易地测试组织承诺的链。我该怎么做?

我要澄清的要点列表:

  • 我应该如何将链开始时可用的数据传递给将在链中间执行的功能?
  • 我应该如何处理promise的结果,以决定下一步该怎么做-中止链或继续执行它?使用resolvereject

0 个答案:

没有答案