Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 56 additions & 67 deletions translations/zh-CN/pages/implementing.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
@title
@primary
Implementing
实现
@secondary
by Forbes Lindesay
Forbes Lindesay 作
Cheng Liu 译

##[intro] Introduction
##[intro] 基本介绍

This article was originally written as an answer on
[Stack Overflow](http://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/23785244#23785244).
The hope is that by seeing how you would go about implementing `Promise` in JavaScript,
you may gain a better understanding of how promises behave.
这篇文章原文发表在 [Stack Overflow](http://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/23785244#23785244).
本文希望能向你展示 `Promise` 在 JavaScript 中的实现,相应地,你将会更加理解 promise 是怎么运行的。

##[state] State Machine
##[state] 状态机

Since a promise is just a state machine, we should start by considering the state information we will need later.
其实一个 promise 就是一种状态机,我们应该考虑到我们接下来会用到的状态信息。

:js
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
// store state which can be PENDING, FULFILLED or REJECTED
// 存储的状态值可以是 PENDINGFULFILLED 或者 REJECTED
var state = PENDING;

// store value or error once FULFILLED or REJECTED
// 一旦状态变为 FULFILLED 或者 REJECTED 时,保存值或者抛出异常
var value = null;

// store sucess & failure handlers attached by calling .then or .done
// 保存通过调用 .then 或者 .done 挂载的正常响应和异常响应的函数
var handlers = [];
}

##[transitions] Transitions
##[transitions] 状态转换

Next, lets consider the two key transitions that can occur, fulfilling and rejecting:
下面,我们一起看看两种状态转换,成功和失败:

:js
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
// store state which can be PENDING, FULFILLED or REJECTED
// 存储的状态值可以是 PENDINGFULFILLED 或者 REJECTED
var state = PENDING;

// store value once FULFILLED or REJECTED
// 一旦状态变为 FULFILLED 或者 REJECTED 时,保存值或者抛出异常
var value = null;

// store sucess & failure handlers
// 保存通过调用 .then 或者 .done 挂载的正常响应和异常响应的函数
var handlers = [];

function fulfill(result) {
Expand All @@ -61,22 +60,21 @@ Next, lets consider the two key transitions that can occur, fulfilling and rejec
}
}

That gives us the basic low level transitions, but lets consider an extra, higher-level
transition called `resolve`
现在我们实现了最简单的状态转换,不过让我们一起想想怎么实现更高层次的状态转换,称为 `resolve`

:js
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
// store state which can be PENDING, FULFILLED or REJECTED
// 存储的状态值可以是 PENDINGFULFILLED 或者 REJECTED
var state = PENDING;

// store value once FULFILLED or REJECTED
// 一旦状态变为 FULFILLED 或者 REJECTED 时,保存值或者抛出异常
var value = null;

// store sucess & failure handlers
// 保存通过调用 .then 或者 .done 挂载的正常响应和异常响应的函数
var handlers = [];

function fulfill(result) {
Expand All @@ -103,14 +101,12 @@ transition called `resolve`
}
}

Note how `resolve` accepts either a promise or a plain value and if it's a promise, waits for it to complete.
A promise must never be fulfilled with another promise, so it is this `resolve` function that we will expose, rather
than the internal `fulfill`. We've used a couple of helper methods, so lets define those:
注意 `resolve` 是如何既能处理 promise 对象又能处理普通值的。如果被传入的是一个 promise,会等待其执行完毕,promise 绝不能直接返回另一个 promise 对象做为执行结果,如同在这个 `resolve` 方法中向我们揭示的那样。此处我们用了一些辅助方法,现在我们来定义他们:

:js
/**
* Check if a value is a Promise and, if it is,
* return the `then` method of that promise.
* 检查传入的值是否是一个 promise 对象,
* 若是,则返回其 `then` 方法
*
* @param {Promise|Any} value
* @return {Function|Null}
Expand All @@ -127,12 +123,11 @@ than the internal `fulfill`. We've used a couple of helper methods, so lets defi
}

/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
* 消除潜在的不正常行为,而且确保 onFulfilled 与 onRejected 只被执行一次
*
* Makes no guarantees about asynchrony.
* 这里不保证异步执行
*
* @param {Function} fn A resolver function that may not be trusted
* @param {Function} fn 一个不能完全信任的处理函数
* @param {Function} onFulfilled
* @param {Function} onRejected
*/
Expand All @@ -155,25 +150,23 @@ than the internal `fulfill`. We've used a couple of helper methods, so lets defi
}
}

##[constructing] Constructing
##[constructing] 构造

We now have the completed internal state machine, but we have yet to expose either
a method of resolving the promise or of observing it. Lets start by adding a way
of resolving the promise.
现在,我们已经完成了内部的状态机,但是我们还没有执行处理函数,让我们开始处理 promise 。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

原文提到了 observing


:js
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
// 存储的状态值可以是 PENDINGFULFILLED 或者 REJECTED
var state = PENDING;

// store value once FULFILLED or REJECTED
// 一旦状态变为 FULFILLED 或者 REJECTED 时,保存值或者抛出异常
var value = null;

// store sucess & failure handlers
// 保存通过调用 .then 或者 .done 挂载的正常响应和异常响应的函数
var handlers = [];

function fulfill(result) {
Expand Down Expand Up @@ -202,37 +195,34 @@ of resolving the promise.
doResolve(fn, resolve, reject);
}

As you can see, we re-use `doResolve` because we have another untrusted resolver.
The `fn` is allowed to call both `resolve` and `reject` multiple times,
and even throw exceptions. It is up to us to ensure that the promise is only resolved
or rejected once, and then never transitions into a different state ever again.
正如你所看到的,我们重用了 `doResolve` 方法,因为我们认为处理函数同样不能被完全信任。
`fn` 方法允许 `resolve` 和 `reject` 可以被多次调用,甚至抛出多个异常。
决定 promise 只能被处理一次、或者只能被执行失败一次,绝不能在不同的状态间多次跳转的职责在我们身上。

##[done] Observing (via .done)
##[done] 观测 (通过 .done)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

中文语序是不是要反过来: (通过 .done) 观测


We now have a completed state machine, but we still have no way to observe any changes to it.
Our ultimate goal is to implement `.then`, but the semantics of `.done` are much
simpler so lets implement that first.
现在,我们有了一个完整的内部状态机,但是我们还没有任何方法能够观测到它的变化。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好像没提到 内部
感觉可以精简一点: 但是我们还 没有任何方法能够 观测到它的变化。 > 但是我们还 无法 观测到它的变化。

我们的终极目标是实现 `.then` 方法,不过语义上来说, `.done` 方法看上去容易实现,
我们就现在实现它吧。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

语病?


Our goal here is to implement `promise.done(onFulfilled, onRejected)` such that:
这里我们要做的,就是实现如下的 `promise.done(onFulfilled, onRejected)` 方法:

- only one of `onFulfilled` or `onRejected` is called
- it is only called once
- it is never called until the next tick (i.e. after the `.done` method has returned)
- it is called regardless of whether the promise is resolved before or after we call `.done`
- 仅被调用一次
- 不会在下一个tick之前被调用 (就是说,`.done` 方法已经返回)
- 调用时与 promise 是否被处理完成无关

:js
var PENDING = 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:js

var FULFILLED = 1;
var REJECTED = 2;

function Promise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
// 存储的状态值可以是 PENDINGFULFILLED 或者 REJECTED
var state = PENDING;

// store value once FULFILLED or REJECTED
// 一旦状态变为 FULFILLED 或者 REJECTED 时,保存值或者抛出异常
var value = null;

// store sucess & failure handlers
// 保存通过调用 .then 或者 .done 挂载的正常响应和异常响应的函数
var handlers = [];

function fulfill(result) {
Expand Down Expand Up @@ -278,7 +268,7 @@ Our goal here is to implement `promise.done(onFulfilled, onRejected)` such that:
}

this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
// 确保此处始终模拟异步执行
setTimeout(function () {
handle({
onFulfilled: onFulfilled,
Expand All @@ -290,13 +280,12 @@ Our goal here is to implement `promise.done(onFulfilled, onRejected)` such that:
doResolve(fn, resolve, reject);
}

We make sure to notify the handlers when the Promise is resolved or rejected.
We only ever do this in the next tick.
我们确保 Promise 状态变更时通知所有处理函数。
这个过程仅发生在下一个 tick

##[then] Observing (via .then)
##[then] 观测 (通过 .then)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上的语序问题? 🤔


Now that we have `.done` implemented, we can easily implement `.then` to
just do the same thing, but construct a new Promise in the process.
现在,我们已经把 `.done` 方法实现好了,我们就能轻易的用同样的办法实现 `.then` 方法,不同的是,在过程中构造了一个新的 Promise 。

:js
this.then = function (onFulfilled, onRejected) {
Expand Down Expand Up @@ -326,14 +315,14 @@ just do the same thing, but construct a new Promise in the process.
});
}

##[apendix] Further Reading
##[apendix] 更多阅读

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

扩展阅读?


- [then/promise](https://github.com/then/promise/blob/master/src/core.js) implements Promise in a very similar way.
- [kriskowal/q](https://github.com/kriskowal/q/blob/v1/design/README.md) is a very different implementation of promises and comes with a very nice walkthrough of the design principals behind it.
- [petkaantonov/bluebird](https://github.com/petkaantonov/bluebird) is a promise implementation that was designed exclusively for performance (along with its own esoteric helper methods). The [Optimization Killers](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) Wiki page is extremely useful for picking up tips.
- [Stack Overflow](http://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/23785244#23785244) is the original source of this article.
- [then/promise](https://github.com/then/promise/blob/master/src/core.js) 简单的实现一个 promise 对象

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

意思应该是 用相似的方法实现 promise ?

- [kriskowal/q](https://github.com/kriskowal/q/blob/v1/design/README.md) 完全不同的方法实现了 promise, 并且一步步的解释了背后的原理
- [petkaantonov/bluebird](https://github.com/petkaantonov/bluebird) 利用黑魔法实现高性能的 promise 对象,[Optimization Killers](https://github.com/petkaantonov/bluebird/wiki/Optimization-killers) 这个维基页面将为你解答其中的奥秘
- [Stack Overflow](http://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/23785244#23785244) 原文链接

@pager
@previous(href="/generators/")
generators
生成器