本文翻译自:Aren't promises just callbacks?
I've been developing JavaScript for a few years and I don't understand the fuss about promises at all. 我已经开发JavaScript几年了,我完全不了解关于promise的麻烦。
It seems like all I do is change: 看来我所做的就是改变:
api(function(result){
api2(function(result2){
api3(function(result3){
// do work
});
});
});
Which I could use a library like async for anyway, with something like: 无论如何我都可以使用像async这样的库,它有类似以下内容:
api().then(function(result){
api2().then(function(result2){
api3().then(function(result3){
// do work
});
});
});
Which is more code and less readable. 哪个代码更多,可读性更差。 I didn't gain anything here, it's not suddenly magically 'flat' either. 我在这里什么都没得到,也不是突然变得神奇地“平坦”。 Not to mention having to convert things to promises. 更不用说必须将事情变成诺言。
So, what's the big fuss about promises here? 那么,这里的诺言有什么大惊小怪的呢?
#1楼
参考:https://stackoom.com/question/1WZdP/不只承诺回调吗
#2楼
Promises are not callbacks. 承诺不是回调。 A promise represents the future result of an asynchronous operation . 许诺代表异步操作的未来结果 。 Of course, writing them the way you do, you get little benefit. 当然,以您的方式编写它们,您会获得很少的收益。 But if you write them the way they are meant to be used, you can write asynchronous code in a way that resembles synchronous code and is much more easy to follow: 但是,如果按照使用它们的方式来编写它们,则可以以类似于同步代码的方式编写异步代码,并且更容易遵循:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
});
Certainly, not much less code, but much more readable. 当然,代码不会太多,但可读性会更高。
But this is not the end. 但这还没有结束。 Let's discover the true benefits: What if you wanted to check for any error in any of the steps? 让我们发现真正的好处:如果您想检查任何步骤中的任何错误怎么办? It would be hell to do it with callbacks, but with promises, is a piece of cake: 用回调来做到这一点将是一件令人头疼的事,但是使用promise却是小菜一碟:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
});
Pretty much the same as a try { ... } catch
block. 与try { ... } catch
块几乎相同。
Even better: 更好的是:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
}).then(function() {
//do something whether there was an error or not
//like hiding an spinner if you were performing an AJAX request.
});
And even better: What if those 3 calls to api
, api2
, api3
could run simultaneously (eg if they were AJAX calls) but you needed to wait for the three? 甚至更好:如果这三个对api
, api2
和api3
可以同时运行(例如,如果它们是AJAX调用),但您需要等待这三个调用怎么办? Without promises, you should have to create some sort of counter. 没有承诺,您应该必须创建某种计数器。 With promises, using the ES6 notation, is another piece of cake and pretty neat: 使用ES6表示法的承诺,是又轻松又整洁的事情:
Promise.all([api(), api2(), api3()]).then(function(result) {
//do work. result is an array contains the values of the three fulfilled promises.
}).catch(function(error) {
//handle the error. At least one of the promises rejected.
});
Hope you see Promises in a new light now. 希望您现在看到一个崭新的承诺。
#3楼
Yes, Promises are asynchronous callbacks. 是的,Promise是异步回调。 They can't do anything that callbacks can't do, and you face the same problems with asynchrony as with plain callbacks. 他们无法做回调不能做的任何事情,并且异步处理和普通回调一样面临同样的问题。
However, Promises are more than just callbacks. 然而,承诺不仅仅是回调多 。 They are a very mighty abstraction, allow cleaner and better, functional code with less error-prone boilerplate. 它们是非常强大的抽象,它允许更简洁,更好的功能代码,并且不易出错。
So what's the main idea? 那么主要思想是什么?
Promises are objects representing the result of a single (asynchronous) computation. 承诺是表示单个(异步)计算结果的对象。 They resolve to that result only once. 他们只解决一次该结果 。 There's a few things what this means: 这意味着几件事:
Promises implement an observer pattern: 承诺实现观察者模式:
- You don't need to know the callbacks that will use the value before the task completes. 您无需在任务完成之前就知道将使用该值的回调。
- Instead of expecting callbacks as arguments to your functions, you can easily
return
a Promise object 您可以轻松地return
Promise对象,而不必将回调作为函数的参数, - The promise will store the value, and you can transparently add a callback whenever you want. Promise将存储该值,并且您可以在需要时透明地添加回调。 It will be called when the result is available. 结果可用时将调用它。 "Transparency" implies that when you have a promise and add a callback to it, it doesn't make a difference to your code whether the result has arrived yet - the API and contracts are the same, simplifying caching/memoisation a lot. “透明度”表示当您有一个诺言并向其添加回调时,结果是否到来对您的代码没有影响-API和协定相同,从而大大简化了缓存/存储。
- You can add multiple callbacks easily 您可以轻松添加多个回调
Promises are chainable ( monadic , if you want ): 承诺是可链接 ( 一元 , 如果你想 ):
- If you need to transform the value that a promise represents, you map a transform function over the promise and get back a new promise that represents the transformed result. 如果需要转换promise表示的值,则可以在promise上映射转换函数,然后获取代表转换结果的新promise。 You cannot synchronously get the value to use it somehow, but you can easily lift the transformation in the promise context. 你不能同步获取的价值以某种方式使用它,但你可以轻松举起的承诺方面的转型。 No boilerplate callbacks. 没有样板回调。
- If you want to chain two asynchronous tasks, you can use the
.then()
method. 如果要链接两个异步任务,可以使用.then()
方法。 It will take a callback to be called with the first result, and returns a promise for the result of the promise that the callback returns. 它将使用第一个结果来调用回调,并为该回调返回的承诺的结果返回承诺。
Sounds complicated? 听起来复杂吗? Time for a code example. 编写代码示例的时间。
var p1 = api1(); // returning a promise
var p3 = p1.then(function(api1Result) {
var p2 = api2(); // returning a promise
return p2; // The result of p2 …
}); // … becomes the result of p3
// So it does not make a difference whether you write
api1().then(function(api1Result) {
return api2().then(console.log)
})
// or the flattened version
api1().then(function(api1Result) {
return api2();
}).then(console.log)
Flattening does not come magically, but you can easily do it. 拼合并不是神奇的方法,但是您可以轻松实现。 For your heavily nested example, the (near) equivalent would be 对于您的大量嵌套示例,(接近)等价于
api1().then(api2).then(api3).then(/* do-work-callback */);
If seeing the code of these methods helps understanding, here's a most basic promise lib in a few lines . 如果看这些方法的代码有助于理解, 以下几行是最基本的promise lib 。
What's the big fuss about promises? 关于承诺的大惊小怪是什么?
The Promise abstraction allows much better composability of functions. Promise抽象允许更好的功能可组合性。 For example, next to then
for chaining, the all
function creates a promise for the combined result of multiple parallel-waiting promises. 例如, then
进行链接的all
函数将为多个并行等待的Promise的组合结果创建一个Promise。
Last but not least Promises come with integrated error handling. 最后但并非最不重要的一点是,Promises带有集成的错误处理。 The result of the computation might be that either the promise is fulfilled with a value, or it is rejected with a reason. 计算的结果可能是,要么承诺满足了值,也被拒绝 ,理由。 All the composition functions handle this automatically and propagate errors in promise chains, so that you don't need to care about it explicitly everywhere - in contrast to a plain-callback implementation. 与纯回调实现相反,所有组合函数都会自动处理此问题并在Promise链中传播错误,因此您无需在任何地方显式地关心它。 In the end, you can add a dedicated error callback for all occurred exceptions. 最后,您可以为所有发生的异常添加专用的错误回调。
Not to mention having to convert things to promises. 更不用说必须将事情变成诺言。
That's quite trivial actually with good promise libraries, see How do I convert an existing callback API to promises? 实际上,对于良好的Promise库来说,这是微不足道的,请参阅如何将现有的回调API转换为Promise?
#4楼
Promises are not callbacks, both are programming idioms that facilitate async programming. 承诺不是回调,它们都是促进异步编程的编程习惯用法。 Using an async/await-style of programming using coroutines or generators that return promises could be considered a 3rd such idiom. 使用使用协程或生成器返回promise的异步/等待式编程可以被认为是第三个这样的习惯用法。 A comparison of these idioms across different programming languages (including Javascript) is here: https://github.com/KjellSchubert/promise-future-task 这些习惯用法在不同编程语言(包括Javascript)中的比较在这里: https : //github.com/KjellSchubert/promise-future-task
#5楼
No promises are just wrapper on callbacks 没有承诺只是回调的包装
example You can use javascript native promises with node js 示例您可以将JavaScript原生Promise与Node JS一起使用
my cloud 9 code link : https://ide.c9.io/adx2803/native-promises-in-node
/**
* Created by dixit-lab on 20/6/16.
*/
var express = require('express');
var request = require('request'); //Simplified HTTP request client.
var app = express();
function promisify(url) {
return new Promise(function (resolve, reject) {
request.get(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body);
}
else {
reject(error);
}
})
});
}
//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
//get the post with post id 100
promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
var obj = JSON.parse(result);
return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
})
.catch(function (e) {
console.log(e);
})
.then(function (result) {
res.end(result);
}
)
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
//run webservice on browser : http://localhost:8081/listAlbums
#6楼
In addition to the already established answers, with ES6 arrow functions Promises turn from a modestly shining small blue dwarf straight into a red giant. 除了已经确定的答案,用ES6箭头功能承诺把从适度闪耀小蓝矮直入一颗红巨星。 That is about to collapse into a supernova: 那即将崩溃成超新星:
api().then(result => api2()).then(result2 => api3()).then(result3 => console.log(result3))
As oligofren pointed out, without arguments between api calls you don't need the anonymous wrapper functions at all: 正如oligofren指出的那样,在api调用之间没有参数,您根本不需要匿名包装器函数:
api().then(api2).then(api3).then(r3 => console.log(r3))
And finally, if you want to reach a supermassive black hole level, Promises can be awaited: 最后,如果您想达到超大质量的黑洞水平,可以等待Promises:
async function callApis() {
let api1Result = await api();
let api2Result = await api2(api1Result);
let api3Result = await api3(api2Result);
return api3Result;
}