2016-08-14 5 views
4

Ich lerne den ES6-Standard, daher beginne ich mit einem sehr einfachen Beispielcode.Wie wandle ich einen Callback-Code in ES6 um?

Es gibt Callback Hells in JavaScript, also möchte ich diesmal Callbacks vermeiden. Aber ich habe ein Problem festgestellt, dass ich nicht wirklich weiß, wie man einen Callback-Stil-Code in ein Versprechen umwandelt.

Zum Beispiel, wenn ich einen solchen Code haben sieht aus wie unten

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); 
    } 
}; 

Wie soll ich wandeln es in ein Promise in ES6? Ist das eine Art empfohlenes Verhalten, das Callbacks in Versprechen umwandelt?

Ich habe dieses Beispiel gelesen, aber ich war tatsächlich durch das Ergebnis verwirrt. Ich denke, bevor ich anfange, meine Rückrufe zu Versprechen neu zu schreiben, muss ich das zuerst verstehen.

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

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

console.log('Hi!'); 

// Promise 
// Hi! 
// Resolved 

Mein Verständnis ist, dass Promise läuft unmittelbar nach erstellt zu werden. Aber ich weiß nicht, warum der Code in then Methode zuletzt ausgeführt wird.

+1

Wenn Sie die Spezifikationen von Promise/A + [hier] (https://promisesaplus.com/) gelesen haben, beachten Sie besonders 2.2.4 und den zugehörigen Hinweis 3.1 - im Grunde sind die '.then 'Callbacks asynchron –

Antwort

2

Die vorhandenen Antworten fallen der deferred anti-pattern. Ich würde diesen Ansatz vermeiden, da er unnötig ausführlich ist und die volle Promise-API nicht nutzt. Eine andere der Antworten verwendet Promistification. Es ist wirklich nur erforderlich, Promistification zu verwenden, wenn Sie den Code, der mit dem Callback-Stil geschrieben wird, nicht ändern können, z. B. mit Skripts von Drittanbietern.

Sie stellen zwei Fragen, die zweite Frage ist, warum Promises sich so verhalten, wie Sie es in Ihrem Beispiel gesehen haben. Um Antworten auf diese Frage zu finden, schlage ich vor, dass Sie die vielen vorhandenen Fragen zu SO dieser Art verwenden. Zum Beispiel aren't Promises just callbacks?

Was Ihre erste Frage, wie Ihr Code Refactoring Versprechen zu verwenden, hier ist mein Vorschlag:

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." 
    }) 

Da die Funktion selbst nicht auf den Abschluss eines asynchronen abhängen Operation können wir die Hilfsmethoden Promise#resolve und Promise#reject verwenden, um eine Promise von der Funktion zurückzugeben, die den Erfolg oder Misserfolg des Erstellens des "Rechteck" -Objekts darstellt. Diese erzeugen ein neues Versprechen, dessen Status aufgelöst oder zurückgewiesen wird, entweder mit einem Wert oder einem Fehler.

+0

Cool das ist genau das, was ich will. Ich werde einige andere Posts über Promise sicher überprüfen. – 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) 
} 

Erinnern Sie sich ".then" und ".catch" ist asynchron.

-1

Versprechen wirklich gut sind, aber am Anfang könnte ein wenig verwirrt, überprüfen Sie diesen Code sein:

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){ 
}); 

In meinem Beispiel, wenn Sie Ihr Modul aufrufen, werden Sie das Versprechen sofort bekommen, aber der Code Noch nicht ausgeführt, nachdem der Code ausgeführt wurde, erhalten Sie das Ereignis in Ihrer "then" -Methode oder wenn etwas in Ihrem Fang passiert.

Ich mag wirklich q-Bibliothek, um Versprechungen zu behandeln, gibt Ihnen eine Menge Kontrolle darüber, wie Sie Fehler zurückgeben und die Kette zu stoppen, wenn etwas falsch passiert. Grundsätzlich haben Sie mehr Kontrolle über Ihren Funktionsablauf.

Ich hoffe es hilft Ihnen

0

Dies ist ein wichtiges Thema. Aus Gründen der synchronen Funktionscodierung besteht der Zweck der Verwendung von Versprechungen darin, die Logik in der Stufe callback zu der then-Stufe zu verschieben. Also, obwohl Sie könnten, sollten Sie nicht mit der Logik innerhalb des Versprechens selbst aber auf der Stufe then umgehen. Diese Denkweise hilft uns, eine Allzweck-Promisify-Dienstprogrammfunktion zu erstellen, die für alle Callback-Strukturen bestimmter Typen funktioniert. In Ihrem Fall ist der Callback-Typ der erste Typ des Knotens Standardfehler. So nach Ihrem Code unter

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); 
    } 
}; 

eine allgemeine Promisfy-Funktion sollte wie folgt funktionieren;

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))

So in diesem speziellen Fall, dass Sie Ihr resultierendes Objekt haben mit den area und perimeter zur then Stufe zugeführt Funktionen onFulfillment als Wert Argument. Dementsprechend sollten Sie die Logik aufrufen, um sie in der onFulfillment Funktion (then Stage First Callback) zu verwenden und alle Fehler in der onReject Funktion (then Stage Second Callback) zu behandeln.Ich zeige dies in der letzten Zeile als Kommentar im obigen Snippet.

PS: Ich benutze v (wie Check aussieht) resolve und x (offensichtlich) zu benennen, die reject Rückrufe von Versprechen zu bezeichnen.

Verwandte Themen