2017-02-24 50 views
1

我无法正确使用JS中的承诺,看起来像什么。如何有效地使用JS Promisses?

我有3个异步相互依赖的功能,像这样:

的func1,func2函数和FUNC 3.

  • func1的返回FUNC2用途的单个结果。
  • func2还返回单个结果
  • func3使用func1和func2的结果。

所以func3必须等待func1和2,而func2只能等待func1。

这里是JS小提琴,我可以编写,它的工作原理,但阅读3一起使用的混乱只是一个nighmare。什么是执行这种连锁经营的正确方法?

function func1() { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(10); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
function func2(return1) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(return1 + 20); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
function func3(val1, val2) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     resolve(val1 + val2); 
 
    }, 1000); 
 
    }); 
 
} 
 

 
func1().then(function(result) { 
 
    func2(result).then(function(result2) { 
 
    func3(result, result2).then(function(finalResult) { 
 
     console.log(finalResult); 
 
    }, function(err) { 
 
     console.log(err); 
 
    }); 
 
    }); 
 
}).catch(function(err) { 
 
    console.log(err); 
 
});

+2

我投票结束这个问题作为题外话,因为如何改进/重新设计工作代码的建议请求属于CodeReview。stackexchange.com。 – Barmar

+0

我不确定还有很大的改进空间。我没有看到多余的代码,它直接表达了设计要求。你是否需要对N个函数进行概括,每个函数都需要得到所有前面函数的结果? – Barmar

+0

您可能也对此感兴趣[如何链接并与承诺共享先前的结果](http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863 #28714863)。这涵盖了在链接承诺时访问多个先前结果的各种选项。 – jfriend00

回答

5

只使用承诺,您可以使用封闭范围和巢您的承诺(这是你在做什么),或者你可以传递多个结果像这样的对象:

func1() 
    .then((result) => { 
    return func2(result).then((result2) => ({result, result2})); 
    }) 
    .then(({result, result2}) => { 
    return func3(result, result2); 
    }); 

或者你可以存储之外的所有承诺的范围结果:

let result; 

func1() 
    .then((_result) => { 
    result = _result; 
    return func2(result); 
    }) 
    .then((result2) => { 
    return func3(result, result2); 
    }); 

如果环境支持async/await functions,你可以把它改写这样的:

async function fn() { 
    const result = await func1(); 
    const result2 = await func2(result); 
    const result3 = await func3(result, result2); 

    return result3; 
} 

fn().then((result3) => console.log(result3)); 

如果您的环境支持发电机,您可以使用co库创建协程:

const fn = co.wrap(function*() { 
    const result = yield func1(); 
    const result2 = yield func2(result); 
    const result3 = yield func3(result, result2); 

    return result3; 
}); 

fn().then((result3) => console.log(result3)); 
+0

我喜欢异步等待,这是更清洁。然而,将结果作为对象符号传递给我似乎是一个糟糕的设计,因为这会表明func2只会被func3使用,因为它实际上将func1的值传递给了进一步链接的func,但它不应该这样。 – Alexus

0

编辑:我误读了要求。 SimpleJ在这里的答案是要走的路。

then回调中返回的值本身是可用的。换句话说,您可以通过返回前一个then回调中的下一个函数来按顺序处理您的承诺。

而不是

func1().then(function(result) { 
 
    func2(result).then(function(result2) { 
 
    func3(result, result2).then(function(finalResult) { 
 
     console.log(finalResult); 
 
    }, function(err) { 
 
     console.log(err); 
 
    }); 
 
    }); 
 
}).catch(function(err) { 
 
    console.log(err); 
 
});

试试这个:

func1() 
 
    .then(result => func2(result)) 
 
    .then(result => func3(result)) 
 
    .then(result => console.log('Final result', result)) 
 
    .catch(err => console.error(err))

我转换了您的功能箭头功能收拾了一下更多,但功能上它和你的一样。

+1

但是func3需要func1和func2的结果,在你的解决方案中它只接受func2的结果。不是吗? – Alexus

+0

啊,是的,我错过了。我会调整答案。 –