async
キーワードでマークされた非同期関数が暗黙的にpromiseを返すことを読みました。
async function getVal(){
return await doSomethingAync();
}
var ret = getVal();
console.log(ret);
しかし、それは一貫性がありません... doSomethingAsync()
がpromiseを返すと仮定すると、awaitキーワードはpromiseの値ではなくpromiseから値を返し、getVal関数shouldはそれを返します暗黙の約束ではなく価値。
それでは、正確には何ですか? asyncキーワードでマークされた関数は、暗黙的にプロミスを返しますか、それとも返すものを制御しますか?
おそらく、明示的に何かを返さなければ、暗黙的に約束を返すのでしょうか...?
より明確にするために、上記との間に違いがあります
function doSomethingAync(charlie) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(charlie || 'yikes');
}, 100);
})
}
async function getVal(){
var val = await doSomethingAync(); // val is not a promise
console.log(val); // logs 'yikes' or whatever
return val; // but this returns a promise
}
var ret = getVal();
console.log(ret); //logs a promise
私の概要では、動作は実際に従来のreturnステートメントと矛盾しています。 async
関数から明示的に非プロミス値を返すと、プロミスで強制的にラップされるようです。それほど大きな問題はありませんが、通常のJSは無視されます。
戻り値は常に約束です。 Promiseを明示的に返さない場合、返される値は自動的にPromiseにラップされます。
async function increment(num) {
return num + 1;
}
// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));
await
があっても同じです。
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function incrementTwice(num) {
const numPlus1 = await defer(() => num + 1);
return numPlus1 + 1;
}
// Logs: 5
incrementTwice(3).then(num => console.log(num));
自動展開を約束するため、async
関数内から値のプロミスを返すと、値のプロミスを受け取ります(値のプロミスのプロミスではありません)。
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function increment(num) {
// It doesn't matter whether you put an `await` here.
return defer(() => num + 1);
}
// Logs: 4
increment(3).then(num => console.log(num));
私の概要では、動作は実際に従来のreturnステートメントと矛盾しています。非同期関数から非プロミス値を明示的に返すと、プロミスで強制的にラップされるようです。それほど大きな問題はありませんが、通常のJSは無視されます。
ES6には、return
とまったく同じ値を返さない関数があります。これらの関数はジェネレーターと呼ばれます。
function* foo() {
return 'test';
}
// Logs an object.
console.log(foo());
// Logs 'test'.
console.log(foo().next().value);
私は仕様を見て、次の情報を見つけました。短いバージョンでは、async function
がPromise
sを生成するジェネレーターに脱糖されます。したがって、はい、非同期関数はpromisesを返します。
tc39 spec によると、次のことが当てはまります。
async function <name>?<argumentlist><body>
脱糖:
function <name>?<argumentlist>{ return spawn(function*() <body>, this); }
spawn
「次のアルゴリズムの呼び出し」:
function spawn(genF, self) {
return new Promise(function(resolve, reject) {
var gen = genF.call(self);
function step(nextF) {
var next;
try {
next = nextF();
} catch(e) {
// finished with failure, reject the promise
reject(e);
return;
}
if(next.done) {
// finished with success, resolve the promise
resolve(next.value);
return;
}
// not finished, chain off the yielded promise and `step` again
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}