Koa2 での async&await の使用法は何ですか?

亚连
リリース: 2018-06-07 15:50:56
オリジナル
1475 人が閲覧しました

この記事では主に、Koa2 での async&await の使用法についての理解を紹介し、参考にさせていただきます。

Koa は非常に有名な Node サーバー側フレームワークであり、1.x バージョンと 2.x バージョンで利用できます。前者は非同期操作にジェネレーターを使用し、後者は最新の async/await ソリューションを使用します

この記述方法を初めて使用し始めたとき、問題が発生しました。コードは次のとおりです:

const Koa = require('koa');
const app = new Koa();

const doSomething = time => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('task done!')
    }, time)
  })
}

// 用来打印请求信息
app.use((ctx, next) => {
  console.log(`${ctx.method}:::${ctx.url}`)
  next()
})

app.use(async ctx => {
  const result = await doSomething(3000)
  console.log(result);
  ctx.body = result
})

app.listen(3000);
ログイン後にコピー

テストしてみましょう:curl http ://localhost:3000

期待される結果:

(3 秒後...)タスク完了!

しかし、現実は:

(すぐに)
見つかりません

一体何?期待どおりのパフォーマンスが得られないのはなぜですか?これには、Koa のミドルウェアがどのように直列に接続されているかを理解する必要があります。ソース コードを見ると、ミドルウェアを連結するコードは次のとおりです。

function compose (middleware) {
 return function (context, next) {
  // 这个index用来计数,防止next被多次调用
  let index = -1
  // 执行入口
  return dispatch(0)
  
  function dispatch (i) {
   // 如果next被多次调用,报异常
   if (i <= index) return Promise.reject(new Error(&#39;next() called multiple times&#39;))
   index = i
   // 取出第一个middleware
   let fn = middleware[i]
   // 将最初传入的next作为最后一个函数执行
   if (i === middleware.length) fn = next
   if (!fn) return Promise.resolve()
   try {
    /**
    这里就是关键了,Promise.resolve是什么意思呢?
     Promise.resolve方法有下面三种形式:
     
     Promise.resolve(value);
     Promise.resolve(promise);
     Promise.resolve(theanable);
     
    这三种形式都会产生一个新的Promise。其中:

    第一种形式提供了自定义Promise的值的能力,它与Promise.reject(reason)对应。两者的不同,在于得到的Promise的状态不同。

    第二种形式,提供了创建一个Promise的副本的能力。

    第三种形式,是将一个类似Promise的对象转换成一个真正的Promise对象。它的一个重要作用是将一个其他实现的Promise对象封装成一个当前实现的Promise对象。例如你正在用bluebird,但是现在有一个Q的Promise,那么你可以通过此方法把Q的Promise变成一个bluebird的Promise。第二种形式可以归在第三种里面
    
    **/
    return Promise.resolve(fn(context, function next () {
     // 执行下一个middleware,返回结果也是一个Promise
     return dispatch(i + 1)
    }))
   } catch (err) {
    return Promise.reject(err)
   }
  }
 }
}
ログイン後にコピー

上記の基礎を踏まえて、なぜ 2 番目のミドルウェアの実行を待たずに応答がすぐに返されるのかを見てみましょう。

最初のミドルウェアは非同期関数ではないためです。

次のメソッドを実行するたびに実際には Promise オブジェクトが返されるため、ミドルウェアで非同期操作を実行し、その完了を待ちたい場合は、ミドルウェアを実行する前に await を追加する必要があります

次に、前のコードを書き直してみましょう

app.use(async (ctx, next) => {
  console.log(`${ctx.method}:::${ctx.url}`)
  await next()
})

app.use(async ctx => {
  const result = await doSomething(3000)
  console.log(result);
  ctx.body = result
})
ログイン後にコピー

わかりました、問題はありません。すべてが期待どおりに実行されます:clap:

エラー処理

Promise と async/await 構文の強力な機能を利用して、try を使用するだけで済みます。 /catch 操作は、後続のすべてのミドルウェア例外をキャプチャできるように、最も外側のミドルウェアに記述されています。

app.use(async (ctx, next) => {
  try{
    await next()
  }catch(err){
    console.log(err)
  }
})

app.use(async (ctx)=>{
  throw new Error(&#39;something wrong!&#39;)
  ctx.body = &#39;Hello&#39;
})
ログイン後にコピー

ミドルウェアチェーンに基づいたフルコントロール、そしてPromiseに基づいているという事実により、すべてが簡単に操作できます。 if (err) return next(err) はもうどこにもありませんが、promise だけです

上記は私が皆さんのためにまとめたものです。将来皆さんのお役に立てれば幸いです。

関連記事:

D3.jsで動的なプログレスバーを実装する方法

vueでモーダルボックスを実装する(一般的な書き方)

Vue.js 2.0でWebApp環境を構築する方法とコルドバ開発

以上がKoa2 での async&await の使用法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート