You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
returnnewPromise((resolve,reject)=>{if(somethingSuccesfulHappened){constsuccessObject={msg: 'Success',
data,//...some data we got back}resolve(successObject);}else{consterrorObject={msg: 'An error occured',
error,//...some error we got back}reject(errorObject);}});
constusers=[{id: '123',name: 'John Smith',posts: [{title: 'Some amazing title',content: 'Here is some amazing content'},{title: 'My favorite title',content: 'My favorite content'},{title: 'A not-so-good title',content: 'The not-so-good content'},]},{id: '456',name: 'Mary Michaels',posts: [{title: 'Some amazing title',content: 'Here is some amazing content'},{title: 'My favorite title',content: 'My favorite content'},{title: 'A not-so-good title',content: 'The not-so-good content'},]},]functiongetUserPosts(id,cb){constuser=users.find(el=>el.id===id);if(cb){if(user){returncb(null,user);}returncb('User Not Found',null);}returnnewPromise(function(resolve,reject){if(user){resolve(user);}else{reject('User not found');}});}/* The above code is collapsed to simulate an API you might use to get user posts for a * particular user from a database. * The API can take a callback as a second argument: getUserPosts(<id>, <callback>); * The callback function first argument is any error and second argument is the user. * For example: getUserPosts('123', function(err, user) { if (err) { console.log(err) } else { console.log(user); } }); * getUserPosts also returns a promise, for example: getUserPosts.then().catch(); * The ID's that will generate a user are the of type string and they are '123' and '456'. * All other IDs will return an error. */getUserPosts('123',function(err,user){if(err){console.log(err);}else{console.log(user);}});getUserPosts('129',function(err,user){if(err){console.log(err);}else{console.log(user);}});getUserPosts('456').then(user=>console.log(user)).catch(err=>console.log(err));
传统上,我们将通过使用回调来访问异步代码的结果。
rrsomeDatabaseThing(maybeAnID,function(err,result)){//...Once we get back the thing from the database...if(err){doSomethingWithTheError(error)}else{doSomethingWithResults(results);}}
promise是什么?
JavaScript promise是一个对象,表示异步任务完成或者失败及其结果值。
完结。
我当然是开玩笑的。那么,这个定义到底意味着什么?
首先,
JavaScript
中的许多东西都是对象。你可以通过几种不同的方式进行创建对象。最常用的方法是使用对象字面量语法:你还可以创建一个
类
,并通过new
关键字对其进行实例化。promise
只是我们创建的对象,就像后面的例子一样,我们使用new
关键字对其进行实例化。我们传入一个带有两个参数的函数,其参数为resolve
和reject
,而不是像传递给我们Car
的三个参数(颜色,类型和门)。最终,
promise
告诉我们一些关于我们从它返回的异步函数的完成情况--生效了或失败了。我们认为这个功能是成功的,如果promise
是解决了,并且说promise
被拒绝是不成功的。看,不是太可怕 -- 只是我们创建的对象。而且,如果我们稍微展开一下:
此外,我们可以传我们喜欢的东西到
resolve
和reject
中。例如,我们可以传递一个对象,而不是一个字符串:或者,为了方便查看,我们任何东西都不传:
定义“异步”的部分怎样?
JavaScript
是单线程的。这意味着它一次只能处理一件事。想象这么条道路,你可以将JavaScript
视为单车道的高速公路。特定代码(异步代码)可以滑动到一边,以允许其他代码越过它。完成异步代码后,它将返回到道路。外号:
promise
为我们提供了一种等待异步代码完成,从中捕获一些值,并将这些值传递给程序其他部分的方法。我这里有篇文章深入探讨这些概念:Thrown For a Loop: Understanding Loops and Timeouts in JavaScript。
我们怎么使用promise?
使用
promise
也称为消费promise
。在上面的示例中,我们的函数返回了一个promise
对象。这允许我们使用方法的链式功能。我打赌你看到过下面的这种链式方法:
现在,(假装)回想下我们的
promise
:然后,通过链式方法调用我们的
promise
:一个(更)真实的例子
想象一下,你有一个从数据库中获取用户的功能。我在codepen上编写了一个示例函数,用于模拟你可能使用的API。它提供了两种访问结果的选项。一,你可以提供回调功能,在其中访问用户或提示错误。或者第二种,函数返回一个
promise
作为用户访问或提示错误的方法。为了方便查看,我把作者的codepen上的代码复制了下来,如下:
传统上,我们将通过使用回调来访问异步代码的结果。
在它们变得过度嵌套之前,回调的使用是可以的。换句话说,你必须为每个新结果运行更多异步代码。回调的这种模式可能会导致“回调地狱”。
Promise
为我们提供了一种更优雅,更易读的方式来查看我们程序流程。写下自己的promise:金发姑娘,三只熊和一台超级计算机
想象一下,你找到了一碗汤。在你喝之前,你想知道汤的温度。但是你没有温度计,幸运的是,你可以使用超级计算机来告诉你汤的温度。不幸的是,这台超级计算机最多可能需要10秒才能获得结果。
这里需要有几点需要注意:
result
的全局变量。Math.random()
和setTimeout()
模拟网络延迟的持续时间。Manth.random()
模拟温度。运行函数并打印结果。
温度是undefined,发生了什么?
该功能需要一定的时间才能运行。在延迟结束之前,不会设置变量。因此,当我们运行该函数时,
setTimeout
是异步的。setTimeout
中的部分代码移出主线程进入等待区域。我这里有篇文章深入研究了这个过程:Thrown For a Loop: Understanding Loops and Timeouts in JavaScript
由于设置变量
result
的函数部分移动到了等待区域直到完成,因此我们的解析器可以自由移动到下一行。在我们的例子中,它是我们的console.log()
。此时,由于我们的setTimeout
未结束,result
仍未定义。那我们还能尝试什么呢?我们可以运行
getTemperature()
,然后等待11秒(因为我们的最大延迟是10秒),然后打印出结果。这是可行的,但这种技术问题是,尽管在我们的例子中,我们知道了最大的网络延迟,但在实际中它可能偶尔需要超过10秒。而且,即使我们可以保证最大延迟10秒,如果
result
出结果了,我们也是在浪费时间。promise来拯救
我们将重构
getTemperature()
函数以返回promise。而不是设置结果。我们将拒绝promise,除非结果是“恰到好处”,在这种情况下我们将解决promise
。在任何一种情况下,我们都会传递一些值到resolve
和reject
。现在,我们可以使用正在返回的promise结果(也称为消费promise)。
.then
,当我们的promise解决时,它将被调用,并返回我们传递给resolve
的任何信息。.catch
,当我们的promise拒绝时,它将被调用,并返回我们传递给reject
的任何信息。最有可能的是,你将更多的使用promise,而不是创建它们。在任何情况下,它们有助于使我们的代码更优雅,可读和高效。
总结
return new Promise((resolve, reject)=> {})
返回一个promise。.then
从已经解决的promise中获取信息,然后使用.catch
从拒绝的promise中获取信息。参考
后话
The text was updated successfully, but these errors were encountered: