Skip to content

Commit 15fde5c

Browse files
committed
添加pro添加promise相关内容
1 parent cab8822 commit 15fde5c

File tree

1 file changed

+171
-3
lines changed

1 file changed

+171
-3
lines changed

async-programing/readme.md

Lines changed: 171 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,12 @@ function* gen(x){
9090
var y = yield x + 2;
9191
return y;
9292
}
93-
9493
var g = gen(1);
95-
g.next() // { value: 3, done: false }
96-
g.next(2) // { value: 2, done: true }
94+
g.next()
95+
// { value: 3, done: false }
96+
g.next(2)
97+
// { value: 2, done: true }
98+
// 这里的g.next(2)相当于向我们的generator函数传入值,作为上一个yield的返回值,所以得到的结果为2
9799
```
98100

99101
通过调用next方法获取到的value代表函数体向外输出的数据,而调用next方法传入的参数本身代表向Generator传入数据。
@@ -502,6 +504,168 @@ function spawn(genF) {
502504
}
503505
```
504506

507+
### 6.promise函数深入理解
508+
509+
每一个promise对象都会提供一个then方法或者是catch方法:
510+
511+
```js
512+
somePromise().then(function () {
513+
// I'm inside a then() function!
514+
});
515+
```
516+
在then方法内部,我们可以做三件事:
517+
518+
1. return 一个promise对象
519+
520+
2. return 一个同步的值或者是 undefined
521+
522+
3.同步的 throw 一个错误
523+
524+
理解这三种情况之后,你就会理解promise了。
525+
526+
#### 6.1 返回另一个promise对象
527+
528+
在有关promise的相关文章中,这种写法很常见,就像上文提到的构成promise链的一段代码:
529+
530+
```js
531+
getUserByName('nolan').then(function (user) {
532+
return getUserAccountById(user.id);
533+
}).then(funcxtion (userAccount) {
534+
});
535+
```
536+
这段代码里面的return非常关键,没有这个return的话,getUserAccountById只是一个普通的被别的函数调用的函数。下一个回调函数会接收到undefined而不是userAccount
537+
538+
#### 6.2 返回一个同步的值或者是 undefined
539+
返回一个 undefined 大多数情况下是错误的,但是返回一个同步的值确实是一个将同步代码转化成promise风格代码的好方法。举个例子,现在在内存中有users。我们可以:
540+
541+
```js
542+
getUserByName('nolan').then(fcuntion (user) {
543+
if (inMemoryCache[user.id]) {
544+
return inMemoryCache[user.id];
545+
// returning a synchronous value!
546+
}
547+
return inMemoryCache[user.id];
548+
// returning a promise
549+
}).then(function (userAccount) {
550+
// I got a user account
551+
})
552+
```
553+
第二个回调函数并不关心userAccount是通过同步的方式得到的还是异步的方式得到的,而第一个回调函数既可以返回同步的值又可以返回异步的值。不幸的是,如果不显式调用return语句的话,javaScript里的函数会返回 undefined 。这也就意味着在你想返回一些值的时候,不显式调用return会产生一些副作用。
554+
555+
因此,我们要养成了一个个人习惯就是在`then方法内部永远显式的调用return或者throw`
556+
557+
#### 6.3 抛出一个同步的错误
558+
说到throw,这又体现了promise的功能强大。在用户退出的情况下,我们的代码中会采用抛出异常的方式进行处理:
559+
560+
```js
561+
getUserByName('nolan').then(function (user) {
562+
if (user.isLoggedOut()) {
563+
throw new Error('user logged out!'); // throwing a synchronous error!
564+
}
565+
if (inMemoryCache[user.id]) {
566+
return inMemoryCache[user.id]; // returning a synchronous value!
567+
}
568+
return getUserAccountById(user.id); // returning a promise!
569+
}).then(function (userAccount) {
570+
// I got a user account!
571+
}).catch(function (err) {
572+
// Boo, I got an error!
573+
});
574+
```
575+
如果用户已经登出的话, catch() 会收到一个同步的错误,如果有promise对象的状态变为rejected的话,它也会收到一个异步的错误。 catch() 的回调函数不用关心错误是异步的还是同步的。
576+
577+
在使用promise的时候抛出异常在开发阶段很有用,它能帮助我们定位代码中的错误。比方说,在then函数内部调用 JSON.parse() ,如果JSON对象不合法的话,可能会抛出异常,在回调函数中,这个异常会被吞噬,但是在使用promise之后,我们就可以捕获到这个异常了。更多关于promise的内容请查看[谈谈使用promise时候的一些反模式](http://www.tuicool.com/articles/FvyQ3a)
578+
579+
下面是摘抄自这个文章的几个例子,弄懂了这几个例子有助于深入的理解Promise。
580+
581+
例子1
582+
583+
```js
584+
doSomething().then(function () {
585+
return doSomethingElse();
586+
//undefined
587+
}).then(finalHandler);
588+
//finalHandler会接受到前面then指定的函数的返回值,因为它明确的return了,注意return不可少
589+
```
590+
答案如下:我们的then方法中没有形参接受到doSomething返回的值,所以为undefined
591+
592+
<pre>
593+
doSomething
594+
|-----------------|
595+
doSomethingElse(undefined)
596+
|------------------|
597+
finalHandler(resultOfDoSomethingElse)
598+
|------------------|
599+
</pre>
600+
601+
例子2
602+
603+
```js
604+
doSomething().then(function () {
605+
doSomethingElse();
606+
}).then(finalHandler);
607+
```
608+
答案如下:finalHandler也会接受到undefined,因为前面的then中的函数没有明确的return值
609+
610+
<pre>
611+
doSomething
612+
|-----------------|
613+
doSomethingElse(undefined)
614+
|------------------|
615+
finalHandler(undefined)
616+
|------------------|
617+
</pre>
618+
619+
例子3
620+
621+
```js
622+
doSomething().then(doSomethingElse())
623+
//doSomethingElse()返回了Promise的情况比较特殊,finalHandler接受到doSomething的值
624+
.then(finalHandler);
625+
```
626+
答案如下:因为我们的then方法中的doSomethingElse()返回的是一个Promise对象,即typeof doSomethingElse()为"object",所以finalHandler会接收到doSomething返回的值。
627+
628+
<pre>
629+
doSomething
630+
|-----------------|
631+
doSomethingElse(undefined)
632+
|---------------------------------|
633+
finalHandler(resultOfDoSomething)
634+
|------------------|
635+
</pre>
636+
637+
比如下面的例子依然输出的为"qinliang":
638+
639+
```js
640+
var f=function(result){console.log(result);}
641+
Promise.resolve("qinliang").then(f);
642+
```
643+
和下面的代码输出结果完全相同:
644+
645+
```js
646+
Promise.resolve('qinliang').then(function(result){console.log(result);})
647+
```
648+
其实他们的then方法传入函数签名完全一致。
649+
650+
例子4
651+
652+
```js
653+
doSomething().then(doSomethingElse)
654+
//doSomethingElse会接受到doSomething()的结果
655+
.then(finalHandler);
656+
//finalHandler会接受到doSomethingElse的结果
657+
```
658+
答案如下:我们的doSomethingElse只是一个`函数句柄(如const doSomething=function(){})`,通过调用这个函数句柄doSomethingElse()会得到我们的Promise对象。
659+
660+
<pre>
661+
doSomething
662+
|-----------------|
663+
doSomethingElse(resultOfDoSomething)
664+
|------------------|
665+
finalHandler(resultOfDoSomethingElse)
666+
|------------------|
667+
</pre>
668+
需要说明的是,在上述的例子中,我都假设 doSomething() 和 doSomethingElse() `返回(注意是返回了,即return的情况下,而不是第一个例子的方式)`一个promise对象,这些promise对象都代表了一个异步操作,这样的操作会在当前event loop之外结束,比如说有关IndexedDB,network的操作,或者是使用 setTimeout 。这里给出 JSBin 上的示例。
505669

506670

507671
参考资料:
@@ -519,3 +683,7 @@ function spawn(genF) {
519683
[co库](https://github.com/tj/co)
520684

521685
[node-thunkify库](https://github.com/tj/node-thunkify)
686+
687+
[谈谈使用promise时候的一些反模式](http://www.tuicool.com/articles/FvyQ3a)
688+
689+
[关于Promise:你可能不知道的6件事](http://www.tuicool.com/articles/6fqQ3aB)

0 commit comments

Comments
 (0)