[フレーム]
1 - 40 件 / 83件
Intro Fetch API の実装が広まり、IE もリタイアを迎えたことで、今後忘れ去られていくことになるだろう XMLHttpRequest について。 どのように始まり、どのように広まり、どのように使われなくなっていくのか。その間に残した多大な功績を残す。 XMLHttpRequest の始まり この名前は非常に長いため、通常 XHR と略される。 この API は、現在の Web API のように W3C/WHATWG による標準化を経て策定された API ではない。Microsoft によるいわゆる独自実装の API として始まり、後追いで標準化される。 したがって、Web API の中でもかなり異質な命名である XHR が、XmlHttpRequest でも XMLHTTPRequest でもなく XMLHttpRequest である理由も、Microsoft の命名規則に「
はじめに JavaScript の非同期処理を学習してみて「ある程度自信を持って理解できたと言える」状態に到達したので、その感想とまとめの学習ロードマップとその中でどのような知識が必要になるかを紹介したいと思います。 あるいは、自分が実際に学習してきた道筋に基づいているのでショートカットとして参考にしてもらったり、使えるリソースなどの情報が共有できると思います。もしくは「JavaScript 初心者が非同期処理を理解できるようになるまでの道筋」というストーリーで1つのサンプルとして見ていただけるといいかもしれません。 ChangeLog 大きな変更のみをトラッキングしています。 2022年11月16日 本の内容を反映させた追記・修正を追加 2022年05月21日 構成を修正 「V8 エンジンから考える」の項目を追加 2022年04月30日 「イベントループの共通性質」の項目を追加 「ロードマップ
JavaScriptはシングルスレッドであることが知られています。そして、Promiseを用いた非同期処理ができることは周知の事実です。では、なぜシングルスレッドで非同期処理ができるのでしょうか? その点について、非同期処理のための2種類のQueuesについて触れつつ、コードベースでの説明も行います。
対象読者と目的 非同期処理の実装方法は知っているが、仕組みを詳しく知らないのでベストプラクティスがわからないときがある 実行順序の保証がよくわからないので自信をもってデプロイできない変更がある より詳しい仕組みを理解することでより計画的な実装をできるようになりたい という動機で書かれた記事です。同様の課題を抱える人を対象読者として想定しています。 目次 実行モデルとタスクキュー Promise async/await AbortSignal, Event, Async Context WHATWG Streams / Node.js Streams (執筆中) 未定 入門記事へのリンク プロミスの使用 - JavaScript | MDN Promise, async/await (現代の JavaScript チュートリアル) JSの初心者にPromiseとasync/awaitの使い方
Promises in JavaScript can seem a bit daunting at first, but understanding what's happening under the hood can make them much more approachable. In this blog post, we'll dive deep into some of the inner workings of promises and explore how they enable non-blocking asynchronous tasks in JavaScript. I'm still working on making this blog better on mobile devices, mobile browsers don't always render t
まとめ async/await 構文は、Promise で書ける処理のうち特定のケースしか表現できない 特定のケースとは、ある非同期処理の前処理と後処理がそれぞれ 1 個ずつの場合のみである async/await 構文は初心者に非同期処理を導入する際に適しているが、非同期処理を逐次処理として書けるという幻想を与えるので、どこかで知識をアップデートする機会を設けるべきである この記事はなに? 少しバズったのでまとめておこうかと。 「async/await があれば Promise なんて難しいものは要らない!」とか言ってるウブな子に、複数の API に並列にリクエストを投げて一つ以上成功した時だけ先に進む、みたいな問題を与えて愛でてみたい。— Yuta Okamoto (@okapies) 2020年12月11日 async/await は Promise のネストを手続き的なコードに見え
JavaScript において、特に苦手とする人が多い印象のある Promise ですが、await と async の文法が導入されたことで、Promise の仕様を深く理解しなくても非同期処理を自然に書けるようになってきたのではないかと思います。 極論ですが、JavaScript の非同期処理は async await new Promise のみで、(ほぼ)全て表現可能です。特別な理由がない限り then を使わないようにしましょう、ということを周知するのがこの記事の目的です。 なお本記事では Promise の rejected の状態についてほとんど解説しておりません。基本を理解したら、別記事でぜひ学んでみてください。 Promise とは? Promise は、少し乱暴に説明すると「実行が終わっていないかもしれない何らかの関数」を包んだオブジェクトです。 普通の関数とは違って、
ブラウザで長いループや、重い処理をともなうループを回したいとき、同期的にJavaScriptを実行するとメインスレッドがブロックしてしまうので、ちょっとずつ細切れに分割して実行したい、ということがある。 昨日久しぶりに書いたら新たなパターンと出会ったので、これまでにどう書いてて今回どうなったかメモ。 setTimeoutする 以前(10年前とか)はこんなのをよく書いていた。 itemsがでかいArrayで、console.logがすごく重い処理だとして読んでください。 function iterateHeavyTask(items) { const startAt = new Date(); while (items.length > 0 && new Date().getTime() - startAt < 10) { console.log(items.shift()); } if (
対象読者と目的 非同期処理の実装方法は知っているが、仕組みを詳しく知らないのでベストプラクティスがわからないときがある 実行順序の保証がよくわからないので自信をもってデプロイできない変更がある より詳しい仕組みを理解することでより計画的な実装をできるようになりたい という動機で書かれた記事です。同様の課題を抱える人を対象読者として想定しています。 目次 実行モデルとタスクキュー Promise async/await AbortSignal, Event, Async Context WHATWG Streams / Node.js Streams (執筆中) 未定 用語に関する注意 前回定義した以下の用語を今回も使います。 1 tick ... タスクキューが1周すること。 1 microtick ... マイクロタスクキューが1周すること。 これらの単位は非同期処理の間の相対的な優先順
この本は、ブルーベリー本の 8 章からインスパイアされて、 TS の型が示す情報から Promise というものを理解してみる、というアプローチで書いたJSの非同期処理の解説です。 これらの資料と合わせて読むことを推奨します。 JSのイベントループのイメージを掴む JSでは中々意識することが少ないですが、正しく理解するには OS レベルのスレッドの視点で考え始める必要があります。 ブラウザや Node.js では一つのスクリプト実行単位を1つのスレッドに割り当てます。それをメインスレッドと呼んだり、ブラウザだったら UI スレッドと呼んだりします。 例えばブラウザでは、これは秒間60回、つまり 16.6ms ごとにループを呼び出します。(node だったらこれがもっと短いです) 仮に setTimeout の実装がなかったとして、それ相当の擬似コードを書くのを試みます。 let handl
対象読者と目的 非同期処理の実装方法は知っているが、仕組みを詳しく知らないのでベストプラクティスがわからないときがある 実行順序の保証がよくわからないので自信をもってデプロイできない変更がある より詳しい仕組みを理解することでより計画的な実装をできるようになりたい という動機で書かれた記事です。同様の課題を抱える人を対象読者として想定しています。 目次 実行モデルとタスクキュー Promise async/await AbortSignal, Event, Async Context WHATWG Streams / Node.js Streams (執筆中) 未定 用語に関する注意 前々回定義した以下の用語を今回も使います。 1 tick ... タスクキューが1周すること。 1 microtick ... マイクロタスクキューが1周すること。 これらの単位は非同期処理の間の相対的な優先
はじめに promiseを使うとき、いつもpromiseメソッドチェーンで記載していますか? async/awaitを利用していますか? もちろん状況によって両方書くのが殆どだとは思うのですが、私はasync/awaitの方が同期的な書き方ゆえに読みやすいため、なるべくそちらで記載しています。しかしながら、エラーハンドリングが理解できていなかったため、エラーの所在を突き止めるのに苦労してしまいました。 そのため、これを機にasync/awaitにおけるエラーハンドリングについて備忘録的にまとめておきます。 この記事のまとめ; catchされるエラーはrejectのみか、throwされたエラーも含まれるか →両方catchできる async関数における処理の順序、awaitがある場合とない場合 →awaitがない場合には同期的に処理が実行され、catchできなくなる エラー処理を外側に伝播し
React Server Components(RSC)は、ページの読み込みパフォーマンスやバンドルサイズのほか、Reactアプリケーションの書き方に近い将来大きな影響を与えることになる、素晴らしい新機能です。 Plasmicでは、Reactのビジュアルビルダーを開発しており、Reactのパフォーマンスには大きな関心を持もっています。 当社のクライアントの多くは、Plasmicを使用して高いパフォーマンスが求められるマーケティングサイトやECサイトを構築しています。 したがって、RSCはまだReact 18の初期実験機能ですが、Plasmicではその仕組みを詳しく調べています。 このブログ記事では、これまでに分かったことを紹介したいと思います。 Plasmicのメンバーによるツイートまとめもご覧ください。 React Server Componentsとは何か サーバサイドレンダリングとの
皆さんこんにちは。最近のReact界隈で話題になっているのは次のRFCです。 そこで、この記事ではさっそくRFCを理解することを目指します。 ただし、このRFCはSuspenseに深く関わるものです。SuspenseはReact 18でもう正式リリースされていますから、この記事ではSuspenseは前提知識とします。もしまだSuspenseをよく知らないのであれば、ぜひ次の記事で学習してください。 また、RFCはあくまでReactの新機能のアイデアを公開するものであり、これが必ず実装されるとは限らない点にご注意ください。例えば、過去にはuseEventというRFCが注目を集めていましたが、意見が集まった結果としてそのRFCは実装されずにクローズされました(RFCが無駄だったというわけではなく、再度検討してよりアイデアがブラッシュアップされることになります)。 新しい use API このR
はじめに JavaScript の「非同期処理」ってやっぱりかなり難しくないですか? 自分も色々試行錯誤しましたが、結局「完全に理解した🤓」→「やっぱり何も分からん😭」っていうループの中で泥臭く理解を深めていくしかないようです。 さて、非同期処理の制御をある程度予測できるようになるには、非同期 API を提供する環境のことやイベントループ、マイクロタスクなどの仕組みについて理解する必要があります。 そして環境に埋め込まれた JavaScript Engine のことも理解する必要があります。 今回の記事では、JavaScript Engine の1つである V8 が内部で変換するコードから async/await の挙動を理解するための解説を試みたいと思います。V8 エンジンからアプローチすることで async/await の分かりづらい挙動を掌握して非同期処理を打倒します。 今回の記
M 年前にも N 年後にも人類は同じ話をしている. まとめ エラーの発生方法は throw と return に大別できる throw には簡潔さ, return には明瞭さと型安全性といった特徴がある どちらの方法がより適しているかはプログラムの規模, エラーの種類, ハンドリングの方法などが判断の材料になる 実際にどちらの方法を使うかは上の判断材料と, フレームワークやプロジェクトのコーディング規約なども合わせて複合的に決めるのがよい エラー発生方法の分類 まず前提として, 関数から呼び出し元にエラーを伝える方法は以下の 2 つに大別できます. 逆にこの記事ではこれ以上の具体的な方法についての議論はしません. throw エラーを throw して呼び出し元に伝える方法です. 例えば以下のようなものが当てはまります. throw new Error("...") Promise.rej
概要 本記事は、HTTP クライアントライブラリである axios の v1.0.0 が満を持してリリースされたため、何がどう変わったのか、マイグレーションしても良いのかについて個人的に調べてまとめた結果になります。 TL;DR axios の v1.0.0 は、パッケージのモダン化に向けた節目としてのバージョンともいえる v1.0.0 では多数のバグ修正と、いくつかの小規模の機能追加がまとめて取り込まれた 破壊的変更や非推奨化は少なからずあるが、基本的な使い方や挙動を大きく変える規模の変更はない 一方で劇的に良くなる変化もないので、急いであげる理由もない 公式マイグレーションガイドは記事執筆時点では提供されていない axios について axios は、JavaScript 向けの HTTP クライアントライブラリの一種で、この種のパッケージとしては比較的古くから普及している老舗ライブラ
そもそも非同期処理とは? Promiseについて知るためには、まず非同期処理について知っておく必要があります。 以下の動画で、非同期処理について100秒で解説しているので、そもそも非同期処理をよく知らないなぁという人はぜひ確認してみてください! Promiseとは では、本題です。 Promiseとは、ES2015で導入された、非同期処理の状態や結果を表現するオブジェクトのことです。 PromiseはES2015で導入された非同期処理の状態や結果を表現するビルトインオブジェクトです。 非同期処理はPromiseのインスタンスを返し、そのPromiseインスタンスには状態変化をした際に呼び出されるコールバック関数を登録できます。 jsprimer - 非同期処理:Promise/Async Function 例えば、出前アプリでピザを注文することをイメージしてみましょう。 ピザを注文すると、
Ruby の開発をしている技術部の笹田です。娘が自転車に乗り始め、まだ不安なためずっとついていなければならず、少し追っかけまわしただけで息切れがヤバい感じになっています。運動しないと。 ここ数年、Ruby で並列処理を気軽に書くための仕組みである Ractor を Ruby 3.0 で導入するという仕事を、クックパッドでの主務として行ってきました(クックパッドから、これ、と言われていたわけではなく、Ruby を前進させるというミッションの上で行ってきました)。 Ractor は、もともと Guild という名前で開発をはじめ、2020年の春頃、Ractor という名前に変更することにしました。いくつかの機会で発表しています。下記は、RubyKaigi での発表の記録です。 A proposal of new concurrency model for Ruby 3 - RubyKaigi
カミナシのソフトウェアエンジニア佐藤です。カミナシレポートの開発に携わっています。 フロントエンドのエラーは「画面リロードやブラウザ再起動で復旧できる(かもしれない)」「クラッシュしてもユーザーの端末に閉じる」などの理由から、バックエンドよりは精緻に扱われない傾向があると個人的には感じています。 その一方、カミナシレポートは、ノンデスクワーカー向けの不安定なネットワーク環境で利用されることも多々あるアプリです。そのため、デジタルツールに不慣れな方のために精緻なフィードバックが必要とされる、リロードに頼ることが難しいケースがある、などの理由でエラーの扱いにも慎重になる必要があります。 本記事では、カミナシレポートのフロントエンド開発をする中で、 バックエンドの API コール時にエラーが発生する条件とその内容(型・クラス) これらエラーをハンドリングする箇所 について、把握しておきたいと感じ
Kyとは Kyは、Sindre Sorhusが開発したJavaScript向けの軽量かつ多機能なHTTPクライアントです。ネーミングの意図はよくわかりませんが、AxiosやネイティブのFetch APIに代わる、より効率的で使いやすい選択肢として設計されています。 Kyの利点 軽量で効率的: Kyのコアは非常に小さく(約2 KB)、パフォーマンスが重要なアプリケーションにとっては特に大きなメリットとなります。 Promiseベース: Fetch APIと同様に、KyはPromiseを基盤としており、async/await構文との組み合わせが容易です。 シンプルなAPI: Kyが提供するAPIは非常にシンプルなので、学習コストが抑えられます。 再試行機能: Kyには、失敗したリクエストの再試行する機能が組み込まれており、エラーハンドリングの実装コストを減らします。 JSON処理: Kyは自動
先日、こちらのツイートを見かけました。 それに対して筆者は以下のツイートをしたところ、いくつかの反応が寄せられました。 コード部分を再掲します。 async function foo1() { return await Promise.resolve(); } async function foo2() { return Promise.resolve(); } async function wait() { await null; } // pika // chu // と表示される foo1().then(() => console.log("pika")); wait().then(() => console.log("chu")); // chu // pika // と表示される foo2().then(() => console.log("pika")); wait().the
JavaScript の非同期処理は非常に難しく、その難しさの原因は「制御の流れ」が掴みづらいことにあります。 この本では非同期処理を理解するために必要な概念であり、仕組みでもあるイベントループでプロミスチェーンの処理がどのように行われるかをクイズ形式で学ぶことによって、非同期処理の「制御の流れ」を掴めるように訓練します。 知識面については中枢となるイベントループの機構から、実行環境と API、async/await や Promise.all などの一通りの範囲を学習し、最終的には並列化や順序づけて反復処理を行うための制御方法と TypeScript での型注釈までを網羅します。
Deleted articles cannot be recovered. Draft of this article would be also deleted. Are you sure you want to delete this article?
Promise と Thenable Promise が ECMAScript の言語仕様に追加されたのは ES2015 ですが, Promise ライクなオブジェクトはそれ以前からも広く使われてきました (jQuery の Deferred など). そういった Promise ライクなオブジェクトとの互換性のため, Promise の仕様は本物の Promise と Promise ライクなオブジェクトを混ぜて使えるようになっています. 具体的には, Promise ライクなオブジェクトは一般に Thenable という共通のインターフェースを持つことになっています. オブジェクトが Thenable であるために必要なのは「then() という名前のメソッドを持っている」という一点のみです. もし Promise を解決 (resolve) するときに使われた値が Thenable
背景 JavaScriptでは forEach という配列から要素を取り出して反復処理できる関数があります。 前の記事 JavaScriptのforEach内でbreakができない理由【備忘録】 では、 forEach の中では break が使えず、途中でループを抜けることができない理由についてまとめました。 今回はその続きとして、forEach の内部で await を使った場合に、非同期処理の完了を待たずに次の処理へ進んでしまう、という挙動について理由を調べてみました。 forEach内でawaitしてみる forEach の中で await して得られた値を配列に追加し、 forEach の直後に配列を console.log で出力する例で確認します。 for文の感覚でいえば、イテレーション中の await で都度処理を待ってくれるイメージなので、全ての要素への処理が終わったら配
名前から既にワクワクするこのAPIは、なんとPromiseを返すsetTimeout、setInterval関数を提供しています!最高です... というわけで今回はそれの紹介です。 基本的な使い方 await setTimeout(1000) ←これができるんです!素晴らしくないですか?? top-level await や for-awaitと組み合わせるとこんな感じで書けます import { setTimeout } from 'timers/promises'; console.log('start'); await setTimeout(1000); // これでいける!! console.log('1s passed'); import { setInterval } from 'timers/promises'; console.log('start'); for await (
ES2015で登場したPromiseとES2017で追加されたasync/awaitによってJavaScriptのコーディングスタイルは大きく変わりました。Promiseの基本的な使い方を理解していることは「脱初心者」のひとつの指標にもなっているようで、網羅的で優れた解説も数多く存在します。 では、基本をおさえた後の活用方法はどうでしょうか? 実際のところ実務ではライブラリやフレームワークから返却されたPromiseをそのままawaitするだけ...という使い方がほとんどかもしれません。しかし、これらのライブラリやフレームワークの中で利用されているような高度なPromiseの活用法をマスターすれば、もっと自由なプログラミングができるようになります。 この記事ではPromiseを活用した実践的な例を3つ紹介します。いずれもライブラリやフレームワークに類似の機能を持つものはありますが、仕組みを理解
JavaScript の forEach は非同期ではない 時々ネットの解説記事で forEach は非同期だという解説を見かけますがこれは間違っています。実際の処理は逐次関数をコールバックしていくだけなので、普通に同期で動いています。コールバック中に非同期処理を使って待機動作を行っていないので、バラバラに動いているように見えるだけなのです。 検証用の非同期処理を作成 ランダムに 1000ms 以内の時間を待機して文字列を出力する関数です。TypeScript になっているので、JavaScript で実行したい場合は型定義を外してください。 const f = (value: string) => { return new Promise<void>((resolve) => setTimeout(() => { console.log(value); resolve(); }, Mat
Go、Python、Kotlin、Rust、TypeScript の5つの言語について「並列処理、並行処理の手法」というテーマに絞り解説する「並列処理をGo/Rust/Kotlin/Python/JSで解説!思想の違いを体感しよう」。JavaScript編では橘氏が登壇。JavaScriptが疑似的な非同期処理をどう実現しているのかと、JavaScriptの非同期処理の歴史について紹介します。 橘氏の自己紹介橘ゆう氏(以下、橘):よろしくお願いします。風邪でめちゃくちゃ顔が死んでいるので、カメラオフでいきます。橘です。今日は「JSの非同期処理パターン Promise、async/awaitを理解する」というテーマについて話していきたいと思います。 簡単な自己紹介ですが、もともとDeNAにいて事業統合でそのままGOに移り、今は森下さん(森下篤氏)と同じチームで、主にサーバーサイドやMLOps
[ English version ] JavaScript と Node.js についてのこの徹底した投稿では、Promises のキャンセルの歴史、なぜNode.jsに関係があるのか、そして async/await APIで使おうとしたときに注意すべきことについて学ぶことができます。 この投稿は、JavaScript の Promise API をよく理解していて、 Node.js の経験がある方のためのものです。 歴史 2014 年に Promise API がブラウザに導入されて以来、人々は Promise で他に何ができるかを調べていました。ブラウザに最初に登場した関連APIは、HTTP リクエストのための fetch() でした。 HTTP リクエストの問題は、サーバーのリソースを消費することであり、サーバーに送信されるリクエストの数が多い場合はお金がかかります。このため、特に
Event Loopってみなさん聞いたことありますか? 「うん、なんか聞いたことありますが、よくわからないな・・・」や「分かりそうで、分からないな・・・」って思ってる方がいますかね? 長文ではありますが、Event Loop というものを改めて理解してみましましょう! まずこのコードの実行結果を考えてみましょう。 console.log('1') setTimeout(function callback(){ console.log('2') }, 1000) new Promise((resolve, reject) => { console.log('3') resolve() }) .then(res => { console.log('4'); }) console.log('5') 答えを分かりますでしょうか?正解はこの後記事内で公開します。 JavaScript 実行の仕組み
準備運動 たとえば「Foo型要素を持つ配列」や「Foo型でfulfillされるPromise」、「Foo型のプロパティ"abc"を持つオブジェクト」の型を定義しようとすると下記のようになる。 type FooArray = Foo[]; type FooPromise = Promise<Foo>; type FooContainer = { abc: Foo }; この記事にたどり着いた人であればここまでは理解できるはず。 inferの使いどころ では逆に、「何かの型を持つ配列」や「何かの型でfulfillされるPromise」、「何かの型のプロパティ"abc"を持つオブジェクト」の「何かの型」を得たい場合はどうするか。 ここでinferの出番となる。 // 注意: このコードは型安全ではありません。 type ArrayOf<T> = T extends (infer U)[] ? U
今月20日にInitial Releaseが予定されているNode.js v15ですが、ここでのunhandled rejectionの挙動変更について解説します。 unhandled rejectionとは async関数内でthrowされたエラーや、rejectされたPromiseが、.catch()などでハンドリングされずにrejectされたままになっている状態を、unhandled rejction(またはunhandled promise rejction)と呼びます。Node.js v14では、unhandled rejectionが発生すると次のような警告が出力されます。 $ node -e "Promise.reject()" (node:22145) UnhandledPromiseRejectionWarning: undefined (Use `node --trac
karino2 が 並列プログラムから見たFuture というビデオを作って公開していたので、引っ越しの荷造りをしながら眺めた。 長いのでここにざっくりとした主張をまとめると: Future/Promise (およびその後釜の async/await) は非同期プログラミングで callback hell にならない発明という見方をされているが、 そもそもなぜ callback hell が必要だったかの時代背景が十分に理解されていない。 背景の一つはブラウザ JavaScript のプログラミングモデルにシングルスレッド・ノンブロッキング(イベントループ)という制限があったから。 これは(特にフロントエンド開発者の間では)よく理解されている。 もう一つの視点は SEDA みたいなマルチスレッド・ノンブロッキング環境の必要性で、 こっちはいまいち広く理解されていないように思える。 結果とし
はじめに twitter 上で議論になっていたネタを本人の許可を得て記載しています。 Node.js でだけ発生する非同期関連の謎現象を発見した🤔 複数回連続で、非同期処理を挟んだ関数から返した非同期関数を、非同期に実行すると allSettled で待ち受けされずにその場で例外が発生する。 これはバグなのかな...https://t.co/w5C9wKEAOA pic.twitter.com/y3pz4ajndF— shqld🦭 (@shqld) January 4, 2022 実はこの話は会社の中でも一回議論になったネタなんですよね。僕も microtask と呼ばれる Promise キューイングの仕組みとイベントループでタスクをハンドリングする仕組みの両方が組み合わさった時に Unhandled Rejection が起きる理由がわかりにくくなるなーと思っています。誤解していた
概要 addEventListenerはブラウザ組み込みのAPIの中でも最もよく使われるメソッドの中の一つだと思います。このメソッドはぱっと見で処理がわかりにくく引数にコールバック関数を取るため、初心者の頃に物凄く読みにくいコードを書いた人も多いのではないでしょうか? addEventListenerが読みにくくなってしまう簡単な例を挙げます。以下のコードのようにAというイベントが発生しないとBというイベントを購読する処理をかけないといったイベント間に依存関係がある場合は、処理が増えるにつれ直感的なコードを書くことが難しくなっていくと思われます。 // <body>より上の位置で<script>にdefer属性なしで書かれてあると思ってください。 document.addEventListener("DOMContentLoaded", () => { console.log("DOMCo
Deleted articles cannot be recovered. Draft of this article would be also deleted. Are you sure you want to delete this article?
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く