2016-08-14 13 views
4

私はES6の標準を学んでいますので、非常に基本的なコードから始めます。コールバックコードをES6で約束する方法

JavaScriptにコールバックヘリングが存在するので、今回はコールバックの使用を避けたいと考えています。しかし、私はコールバックスタイルのコードを約束事に変換する方法がわからないという問題に直面しました。私は、このようなコードがある場合たとえば

は、

私はES6で Promiseに変換する必要がありますどのよう
module.exports = (x, y, callback) => { 
    try { 
    if (x < 0 || y < 0) { 
     throw new Error('Rectangle dimensions are wrong.'); 
    } else { 
     callback(null, { 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    callback(error, null); 
    } 
}; 

以下のように見えますか?コールバックを約束に変換するのは、ある種の推奨動作ですか?

私はこの例を読んだことがありますが、私は結果で実際に混乱しました。私はコールバックを約束に書き換える前に、まずこのことを理解する必要があると思います。

let promise = new Promise(function(resolve, reject) { 
    console.log('Promise'); 
    resolve(); 
}); 

promise.then(function() { 
    console.log('Resolved.'); 
}); 

console.log('Hi!'); 

// Promise 
// Hi! 
// Resolved 

私の理解では、Promiseの実行直後に、作成したばかりということです。しかし、なぜthenのコードが最後に実行されるのかわかりません。

+1

もしPromise/A + [here](https://promisesaplus.com/)の仕様を読んで2.2.4と注意3.1に注意を払うなら、基本的に '.then'コールバックは非同期です。 –

答えて

2

既存の回答はdeferred anti-patternになります。私は不必要に冗長で、完全なPromise APIを利用していないので、このアプローチは避けています。答えのもう一つは、約束を使用しています。サードパーティ製のスクリプトなど、コールバックスタイルを使用して記述されたコードを変更できない場合は、プロミスキーションを使用するだけで十分です。

あなたは2つの質問をしています。その2つ目は、プロミスがあなたの例で見たように振る舞う理由です。この質問に対する回答を見つけるために、私はこの性質のSOに関する多くの既存の質問を使用することをお勧めします。関数は、非同期の完了に依存しませそのものんので

module.exports = (x, y) => { 
    if (x < 0 || y < 0) { 
    return Promise.reject(new Error('Rectangle dimensions are wrong.')); 
    } else { 
    return Promise.resolve({ 
     perimeter() { 
     return (2 * (x + y)); 
     }, 
     area() { 
     return (x * y); 
     }, 
    }); 
    } 
}; 

// e.g. success 
createRectangle(10, 10) 
    .then(rect => { 
    console.log(rect.area()) //=> 100 
    }) 

// e.g. failure 
createRectangle(-1, -1) 
    .catch(err => { 
    console.log(err) //=> "Error: Rectangle dimensions are wrong." 
    }) 

:たとえば、約束を使用するようにコードをリファクタリングする方法についてのあなたの最初の質問、についてはaren't Promises just callbacks?

は、ここに私の提案ですオペレーションでは、ヘルパーメソッドPromise#resolvePromise#rejectを使用して、「長方形」オブジェクトの作成の成功または失敗を表す関数からPromiseを返すことができます。これらは、ステータスがそれぞれ値またはエラーのいずれかで解決または拒否される新しいPromiseを生成します。

+0

Coolこれはまさに私が欲しいものです。プロミスについての他の投稿を確認します。 – Kulbear

0
module.exports = (x, y, callback) => { 
    new Promise(function(resolve, reject) { 
    if (x < 0 || y < 0) reject(new Error('Rectangle dimensions are wrong.')) 
    else resolve({ 
     perimeter() { 
     return (2 * (x + y)); 
     }, 
     area() { 
     return (x * y); 
     } 
    }) 
    }) 
    .then(callback) 
    .catch(callback) 
} 

「.then」と「.catch」は非同期です。

-1

約束は本当に良いですが、初めに、少し混乱するこのコードをチェックすることもできます

module.exports = (x, y) => { 
var deferred = q.defer();// this will be our promise 
    try { 
    if (x < 0 || y < 0) { 
     //return an error to be catched by catch method 
     deferred.reject(new Error('Rectangle dimensions are wrong.')); 
    } else { 
     //return the event to the next function with this value 
     deferred.resolve({ 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    deferred.reject(error); 
    } 

return deferred.promise; //Here return the promise 
}; 

//You will use it like this 
module(x,y) 
.then(callback) 
.then(function(data){ 
}) 
.catch(function(error){ 
}); 

私の例では、あなたのモジュールを呼び出すとき、あなたはすぐに約束が、コードを取得しますまだ実行されていない場合、コードが実行された後、あなたは「then」メソッドでイベントを取得します。

私は、約束事を処理するためにqライブラリが本当に好きです。エラーを返す方法を教えてください。基本的には、関数のフローをより詳細に制御できます。

希望します。

0

これは重要なトピックです。同期的に見える方法で機能的にコーディングするために、約束を使用する点は、callbackのロジックをthenステージに移動することです。ですから、あなたは約束の中で論理を扱うべきではありませんが、thenの段階で論理を扱うべきです。このような考え方は、特定のすべての型コールバック構造で機能する汎用関数promisifyユーティリティ関数を作成するのに役立ちます。あなたのケースでは、コールバック型はNode標準エラーの最初の型です。したがって、以下のコードに従って

module.exports = (x, y, callback) => { 
    try { 
    if (x < 0 || y < 0) { 
     throw new Error('Rectangle dimensions are wrong.'); 
    } else { 
     callback(null, { 
     perimeter() { 
      return (2 * (x + y)); 
     }, 
     area() { 
      return (x * y); 
     }, 
     }); 
    } 
    } catch (error) { 
    callback(error, null); 
    } 
}; 

一般的なpromisfy関数は次のように動作します。

var moduleExports = (x, y, callback) => { 
 
    try { 
 
    if (x < 0 || y < 0) { 
 
     throw new Error('Rectangle dimensions are wrong.'); 
 
    } else { 
 
     callback(null, { 
 
     perimeter() { 
 
      return (2 * (x + y)); 
 
     }, 
 
     area() { 
 
      return (x * y); 
 
     }, 
 
     }); 
 
    } 
 
    } catch (error) { 
 
    callback(error, null); 
 
    } 
 
}; 
 

 
function promisfy(fun, ...args){ 
 
    return new Promise((v,x) => fun(...args, (err,data) => !!err ? x(err) : v(data))); 
 
} 
 

 
var p = promisfy(moduleExports,4,5); 
 
p.then(val => console.log(val,val.area(),val.perimeter()), err => console.log(err)); 
 

 
// p.then(val => callback(null,val), err => callback(err))

したがって、この特定のケースでは、あなたは値を引数としてthen段階onFulfillmentに供給areaperimeter機能を使用して、その結果のオブジェクトを持っています。したがって、onFulfillment関数(thenステージファーストコールバック)でそれらを利用するロジックを呼び出し、onRejectファンクション(thenステージ第2コールバック)のエラーを処理する必要があります。最後の行でこれを上記のスニペットのコメントとして示します。

PS:私は約束のrejectコールバックを指定する(明らか)resolvexを指定する(チェックのように見える)vを使用しています。