読者です 読者をやめる 読者になる 読者になる

ぱんだのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

Promiseとresolve関数

Promiseコンストラクタには、<<非同期処理を書いた関数>>(executor)を引数として渡します.
executor関数はresolve, rejectと呼ばれる2つの関数を引数として取ります.
executor内で、非同期処理が終わった後にresolve(value)を呼ぶとthenのonfulfilled関数が呼ばれますね.
で、このresolve()が一体なんなのか、について仕様書をひっくり返してみました.

結論

resolve(), reject()はanonymous built-in function(組み込みの無名関数)

前提

Promiseを作るときは

new Promise( function(resolve, reject){
                 ...
                 if(success){
                     resolve(value);
                 }
             })

みたいな感じで作るが、
resolve, rejectの関数名は任意.(executorの引数名を変えて試してみればわかる.)
こいつらなんだ…と思い、調べてもわからぬので仕様書を読み解いた.

本論

Promiseコンストラクタの内部処理

.1. If NewTarget is undefined, throw a TypeError exception.
.......
.8. Let resolvingFunctions be CreateResolvingFunctions(promise).
.......
.11. Return promise.
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise-executor

CreateResolvingFunctions()が関係深そう.

CreateResolvingFunctions ( promise )

......
.2. Let resolve be a new built-in function object as defined in Promise Resolve Functions (25.4.1.3.2).
......
.8. Return a new Record { Resolve: resolve, Reject: reject }.
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-createresolvingfunctions

組み込みの無名関数をresolveに入れてますね、これだ.

25.4.2.Promise Resolve Functions

A promise resolve function is an anonymous built-in function ...
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise-resolve-functions

ビンゴー!

整理

CreateResolvingFunctions ( promise )

'1. alreadyResolved = Record { value: false };
.2. resolve = (anonymous built-in) Promise Resolve Function;
'3. resolve.Promise = promise;
'4. resolve.AlreadyResolved = alreadyResolved;
'5. reject = (anonymous built-in) Promise Reject Function;
'6. reject.Promise = promise;
'7. reject.AlreadyResolved = alreadyResolved; .8. Return Record { Resolve: resolve, Reject: reject };

もっと整理 CreateResolvingFunctions (Promise)

.2. resolve = (anonymous built-in) Promise Resolve Function;
3-4.
resolve{
Promise: promise,
AlreadyResolved: Record { value: false }; (1より)
}

'5. reject = (anonymous built-in) Promise Reject Function;
6-7.
reject{
Promise: promise;
AlreadyResolved = Record { value: false }; (1より)
}

.8. Return Record { Resolve: resolve, Reject: reject };

7.3.12 Call(F, V, [argumentsList])

'1. ReturnIfAbrupt(F);
'2. If(argumentsList == undifined){ argumentsList = ;}
'3. Error handling. '4. Return F.[Call];
[http://www.ecma-international.org/ecma-262/6.0/index.html#sec-call]

9.2.1 [[Call]] ( thisArgument, argumentsList)

'1. Assert
'2. Error handling.
'3. callerContext = the running execution context;
'4. calleeContext = PrepareForOrdinaryCall(F, undefined);
'5. Assert
'6. OrdinaryCallBindThis(F, calleeContext, thisArgument);
'7. result = OrdinaryCallEvaluateBody(F, argumentsList);
'8. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
'9. If(result.[[type]] ==return){ return NormalCompletion(result.[[value]]);};
== return Completion{[[type]]: normal, [[value]]: result.[[value]], [[target]]:empty};
'10. ReturnIfAbrupt(result).
'11. Return NormalCompletion(undefined).
== return Completion{[[type]]: normal, [[value]]: undefined, [[target]]:empty};

9-11. // 必ず Completionが返る
If(result.[[type]] == return) return Completion{[[type]]: normal, [[value]]: result.[[value]], [[target]]:empty};
elseIf(result == abrupt completion) return result;
else return Completion{[[type]]: normal, [[value]]: undefined, [[target]]:empty};

コンストラクタのコール

'9. completion = Call(executor, undefined, «built-in Resolve F, built-in Reject F»);
-->
Call.4.
'4. Return executor.[Call];

Promise( executor )

  1. Error handling.
  2. Error handling.
  3. promise = OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", «‍[[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]]» ).
  4. ReturnIfAbrupt(promise).
  5. promise.[[PromiseState]] = "pending";
  6. promise.[[PromiseFulfillReactions]] = ;
  7. promise.[[PromiseRejectReactions]] = ;
  8. resolvingFunctions = CreateResolvingFunctions(promise);
  9. completion = Call(executor, undefined, «resolvingFunctions.Resolve, resolvingFunctions.Reject»); If(completion == abrupt completion){ status = Call(resolvingFunctions.Reject, undefined, «completion.value»);
    ReturnIfAbrupt(status); }
  10. Return promise;

より整理 Promise( executor )

1-2. Error handling.

'3. promise = OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", «‍PromiseState, PromiseResult, PromiseFulfillReactions, PromiseRejectReactions» ).

'4. ReturnIfAbrupt(promise).

5-7. promise{
PromiseState: "pending",
PromiseFulfillReactions: ,
PromiseRejectReactions: ;
}

'8. resolvingFunctions = CreateResolvingFunctions(promise);

'9. completion = Call(executor, undefined, «resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]]»);

'10.
If(completion == abrupt completion){
status = Call(resolvingFunctions.[[Reject]], undefined, «completion.[[value]]»);
ReturnIfAbrupt(status);
}

'11. Return promise;

統合と整理 Promise( executor )

1-2. Error handling.

'3. promise = OrdinaryCreateFromConstructor(NewTarget, "%PromisePrototype%", «‍[[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]]» ).
'4. ReturnIfAbrupt(promise).

5-7. promise{
[[PromiseState]]: "pending",
[[PromiseFulfillReactions]]: ,
[[PromiseRejectReactions]]: [];
}

'8. built-in function準備

'9. completion = Call(executor, undefined, «built-in Resolve F, built-in Reject F»);

'10.
If(completion == abrupt completion){
status = Call(built-in Reject F, undefined, «completion.[[value]]»);
ReturnIfAbrupt(status);
}

'11. Return promise;