ホームページ  >  記事  >  ウェブフロントエンド  >  asyncとawaitの使い方を詳しく解説

asyncとawaitの使い方を詳しく解説

php中世界最好的语言
php中世界最好的语言オリジナル
2018-03-23 15:16:365247ブラウズ

今回は、async と await の使い方について詳しく説明します。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 番目のミドルウェアの実行を待たずに応答がすぐに返されるのかを見てみましょう。

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

next メソッドを実行するたびに実際には 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('something wrong!')
  ctx.body = 'Hello'
})
ミドルウェアチェーンに基づいたフルコントロール、そしてPromiseに基づいているという事実により、すべてが簡単に操作できます。どこにでも if (err) return next(err) はなくなりましたが、promise だけが存在します

この記事のケースを読んだ後は、このメソッドを習得したと思います。さらに興味深い情報については、PHP 中国語に関する他の関連記事に注目してください。 Webサイト!

推奨読書:

datepickerの使い方

mixinの上位コンポーネントの使用方法の詳細な説明

Vue.jsでのejsExcelテンプレートの使用

以上がasyncとawaitの使い方を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。